[Database] MYSQL - VARCHAR vs TEXT

2023. 6. 30. 11:33·개발/Database
728x90
반응형

게시글 작성시 DB저장시 내용부분의 타입은 뭘로 쓸지 VARCHAR로 하면 길이는 얼마나 줘야할지 고민했다.

이참에 VARCHAR와 TEXT의 차이를 알아보고 앞으로 어떤 타입을 적용시키는게 좋을까를 정리하려고 한다.

모든 테이블은 InnoDB를 기반으로 한다.

 

1. VARCHAR

varchar은 variable character 즉 가변적인 캐릭터이다.

char 타입과 비교해보면 char 타입은 고정 크기이고 varchar은 가변 크기인 것이다.

varchar를 설정할때 항상 괄호 안에 있는 숫자가 글자 수인지 바이트 수 인지 헷갈렸다. -> 글자 수라고 한다.

즉 varchar(255) 라고 설정하면 255자 이하의 문자열을 사용할 수 있다.

varchar은 최대 65535개의 문자열을 저장할 수 있다고 하지만 실제론 그렇지 않다.

mysql 공식문서에서 보면 다음과 같이 설명한다.

mysql> CREATE TABLE t1
       (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
       ENGINE = InnoDB CHARACTER SET latin1;
Query OK, 0 rows affected (0.02 sec)

MYSQL의 row에는 각각 65565바이트를 할당할 수 있는데 전체 바이트이다.

varchar(65535) 처럼 varchar 하나의 최대 크기제한이 아닌것이다.

 

varchar는 주어진 길이를 기록할 때 길이만큼 바이트가 필요하다.

255 이하는 1바이트, 256부터는 2바이트가 필요한 것이다.

 

그렇기 때문에 위 같은 경우는 (32765 + 2) + (32766 + 2) = 65535 로 실행이 가능한 것이다.

여기에 varchar(1) 의 테이블을 추가했다면 오류가 날것이다.

로마자라고 불리는 latin 은 한 글자에 1바이트라고 한다.

 

여기서 character set 만 utf-8 로 바꾸면 어떻게 될까

CREATE TABLE t2
       (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
       ENGINE = InnoDB CHARACTER SET utf8mb3;

여기서 utf8mb3 는 max bite가 3인 utf-8이다.

 

이 쿼리를 날려보면 실패한다.

Column length too big for column 'c1' (max = 21845); use BLOB or TEXT instead

왜 최대가 21845라고 오류가 나는것일까..

왜냐하면 max byte를 3으로 설정했기 때문에 한글자당 3바이트로 계산한 것이다.

그래서 max = 65535 / 3 = 21845 의 오류가 난다.

 

mysql> CREATE TABLE t2
    ->        (c1 VARCHAR(21845) NOT NULL)
    ->        ENGINE = InnoDB CHARACTER SET utf8mb3;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

그렇다고 21845로 길이를 설정해도 오류가 난다.

왜냐하면 길이를 기록하는데 2바이트(255자 이하라면 1바이트)가 필요하기 때문에 이를 제외하여 21844로 설정해야 한다.

UTF-8은 최대 4바이트까지 지원하는데  각 바이트는 다음 표와 같다.

1바이트 영어
2바이트 한글, 한문 등
3바이트 Ω(오메가) 같은 특수기호
4바이트 이모티콘 등

 

2. TEXT

TEXT는 최대 길이가 65535자인 가변길이 문자열을 보유할 수 있다.

이것만 본다면 VARCHAR와 별 차이가 없다.

 

TEXT의 길이를 포함한 행 전체크기가 65535 바이트를 넘지 않는다면 행 자체내에 저장되지만

65535바이트를 넘는다면 "text blobs" 라는 외부 저장소에 따로 저장한다.

그리고 행 자체 내에는 text blobs의 위치에 대한 포인터를 저장해 놓는다.

포인터는 64비트 시스템 기준 8바이트라고 한다.

즉 엄청난 길이의 TEXT를 8바이트만으로 값을 저장할 수 있는 것이다.

 

TEXT는 길이마다 종류가 있기 때문에 길이를 기록하지 않는다.

길이를 기록할 필요가 없기 때문에 VARCHAR의 경우 길이 기록에 사용하는 1,2바이트가 필요 없다.

 

TINYTEXT 최대 255바이트
TEXT 최대 65,535바이트
MEDIUMTEXT 최대 16,777,215바이트
LONGTEXT 최대 4,294,967,295바이트

 

이것만 보면 무조건 VARCHAR보다 TEXT가 좋아보인다.

하지만 좋은만큼 안좋은 부분도 있다.

텍스트가 너무 크지 않으면 VARCHAR로 설정하는게 좋은 이유는 TEXT에 비해 쿼리 및 인덱싱 성능이 더 좋다고 한다.

sql 문에서 VARCHAR은 되지만 TEXT는 안되는 연산이 있다고 한다.

 

결론

애초에 나는 게시글의 본문 부분을 고민했기 때문에 TEXT를 사용하기로 결정하였다.

앞으로 애매한 길이의 문자열을 저장할 상황이 생겼을때는 정리한 내용을 토대로 고민하고 결정하여 쓸 수 있을 것 같다.

 

 

 

 

참고

 

MySQL :: MySQL 8.0 Reference Manual :: 8.4.7 Limits on Table Column Count and Row Size

8.4.7 Limits on Table Column Count and Row Size This section describes limits on the number of columns in tables and the size of individual rows. MySQL has hard limit of 4096 columns per table, but the effective maximum may be less for a given table. The

dev.mysql.com

 

 

Difference between VARCHAR and TEXT in MySQL

When we create a table in MySQL with a VARCHAR column, we have to set the length for it. But for TEXT type we don't have to provide the length. What are the differences between VARCHAR and TEXT?

stackoverflow.com

 

728x90
반응형

'개발 > Database' 카테고리의 다른 글

[DB] MySQL 인덱스 사용 가이드  (0) 2025.07.13
[DB] - MySQL B-Tree  (0) 2025.07.11
[MySQL] MySQL 비밀번호 정책 설정 및 변경 방법  (0) 2025.01.04
'개발/Database' 카테고리의 다른 글
  • [DB] MySQL 인덱스 사용 가이드
  • [DB] - MySQL B-Tree
  • [MySQL] MySQL 비밀번호 정책 설정 및 변경 방법
TeTedo.
TeTedo.
  • TeTedo.
    TeTedo 개발 일기
    TeTedo.
  • 전체
    오늘
    어제
    • 분류 전체보기 (319)
      • 개발 (274)
        • Article (4)
        • 정리 (21)
        • Spring Boot (17)
        • JPA (2)
        • JAVA (6)
        • Database (4)
        • 자료구조 (11)
        • 알고리즘 (32)
        • React (20)
        • Docker (10)
        • node.js (18)
        • Devops (11)
        • Linux (4)
        • TypeScript (3)
        • Go (10)
        • HyperLedger (4)
        • BlockChain (43)
        • html, css, js (48)
        • CS (3)
        • AWS (3)
      • 모아두고 나중에 쓰기 (3)
      • 팀프로젝트 (18)
        • SNS(키보드워리어) (9)
        • close_sea (9)
      • 개인프로젝트 (1)
        • Around Flavor (1)
        • CHAM (13)
        • ethFruitShop (5)
      • 독서 (0)
        • 스프링부트와 AWS로 혼자 구현하는 웹 서비스 (0)
  • 블로그 메뉴

    • 홈
    • 개발일기
    • CS
    • 실습
    • 코딩테스트
    • 웹
    • Go
    • node.js
    • 팀플
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    mysql
    30일챌린지
    node
    하이퍼레저
    erc20
    html
    ERC721
    go언어
    30일 챌린지
    CSS
    프로그래머스
    블록체인
    js
    명령어
    도커
    React
    컨테이너
    nodejs
    go
    node.js
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
TeTedo.
[Database] MYSQL - VARCHAR vs TEXT
상단으로

티스토리툴바