게시글 작성시 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를 사용하기로 결정하였다.
앞으로 애매한 길이의 문자열을 저장할 상황이 생겼을때는 정리한 내용을 토대로 고민하고 결정하여 쓸 수 있을 것 같다.
참고
'개발 > Database' 카테고리의 다른 글
[MySQL] MySQL 비밀번호 정책 설정 및 변경 방법 (0) | 2025.01.04 |
---|