MySQL에서 VARCHAR와 TEXT는 모두 문자열 저장에 사용되는 데이터 타입이다.
두 타입 모두 65,535 bytes까지 저장 가능하다.
VARCHAR 타입은 컬럼 선언 시 저장할 문자열의 최대 길이를 명시해야 하며, 해당 길이까지 저장할 수 있다.
TEXT 타입은 별도로 최대 길이를 지정하지 않고, 타입별로 미리 정해진 최대 크기까지 저장 가능하다.
컬럼/타입 선언
CREATE TABLE TMP_TABLE ( V_COL1 VARCHAR(10), V_COL2 TEXT -- 최대 65,535 바이트 저장 가능 );
TEXT 타입의 컬럼 인덱스를 생성할 때 반드시 Prefix(접두) 길이를 지정해야 한다.
인덱스 생성
CREATE INDEX IDX_COL1 (V_COL1); -- 기존 방식으로 생성 불가능 -- TEXT 전체에 직접 인덱싱 불가 CREATE INDEX IDX_COL2 (V_COL2); ❌ -- 반드시 Prefix(접두) 길이를 지정해야 한다. -- TEXT 문자 앞 100 bytes만 인덱싱 CREATE INDEX IDX_COL2 (V_COL2(100));
컬럼에 디폴트 값 지정시 TEXT 타입은 표현식으로만 지정 가능하다.
CREATE TABLE TMP_TABLE ( V_COL1 VARCHAR(10) DEFAULT '기본값', V_COL2 TEXT DEFAULT ('기본값') -- 표현식 () 사용으로 기본값 지정 );
일반적으로 문자의 길이가 짧으면 VARCHAR 타입, 길면 TEXT 타입을 사용한다. 하지만 문자의 길이는 상대적으로 판단되기 때문에 명확한 기준이 없다.
VARCHAR 타입은 메모리 버퍼 공간을 미리 할당하여 재활용하는 방식으로 사용한다. 하지만, TEXT 타입은 매번 필요한 크기만큼 메모리를 할당/해지해야 함으로 오버헤드가 더 크다는 단점이 있다.
이러한 이유로 문자 컬럼을 빈번하게 사용한다면 VARCHAR 타입을 사용하는 게 조금 더 효율적이다.
MySQL은 내부에서 records[2]라는 메모리 버퍼를 사용해 레코드 데이터를 주고받는데, 이 버퍼는 테이블의 최대 컬럼 크기에 맞춰 한 번만 할당되어 여러 연결에서 재사용된다.
VARCHAR 타입은 최대 크기가 정해져 있어 이 버퍼에 공간이 미리 할당되지만, TEXT나 BLOB 같은 큰 데이터(LOB)는 최대 크기만큼 미리 공간을 할당하면 메모리 낭비가 심해서, 별도로 메모리를 매번 할당하고 해제함.
따라서 LOB 타입 컬럼을 읽을 때는 매번 메모리 할당이 필요해 성능에 영향을 줄 수 있다. 또한, VARCHAR라도 값이 커서 Off-Page 저장되는 경우에는 버퍼를 쓰지 못하고 별도의 메모리를 할당하기 때문에 큰 값을 자주 다루면 주의가 필요하다.
모든 TEXT 타입이 별도의 데이터 페이지(Off-Page)에 저장되는 것은 아니다. TEXT 타입의 데이터 크기가 작은 경우에는 기존 레코드에 저장(In-Page) 된다.
일반적으로 하나의 ROW에 담을 수 있는 공간이 약 8,100 bytes로 제한(데이터 페이지의 크기가 16KB)되어 있을 때 이를 초과하는 데이터가 추가될 경우 별도의 데이터 페이지(Off-Page)에 저장된다.
이는 TEXT 타입 뿐만 아니라 VARCHAR타입에도 적용되는 개념이다.
ROW 최대 크기는 65KB지만, 실제 In-Page 저장은 약 8KB 정도로 제한됨.
문자의 크기가 큰 커럼들이 자주 추가되고, 문자의 크기가 큰 컬럼이 많아 ROW 크기 초과가 우려된다면, TEXT를 사용하여 데이터를 row 외부 별도의 데이터 페이지(Off-Page)에 저장함으로써 ROW 크기 제한 문제를 회피할 수 있다.
VARCHAR
- 최대 길이가 (상대적으로) 크지 않은 경우
- 테이블 데이터를 읽을 때 항상 해당 컬럼이 필요한 경우
- DBMS 서버의 메모리가 (상대적으로) 충분한 경우
TEXT
- 최대 길이가 (상대적으로) 큰 경우
- 테이블에 길이가 긴 문자열 타입 컬럼이 많이 필요한 경우
- 테이블 데이터를 읽을 때 해당 컬럼이 자주 필요치 않은 경우
COL1을 VARCHAR(50)으로 생성하고, COL2를 VARCHAR(255)로 생성할 때 다음과 같은 궁금증이 생길 수 있다.
COL1과 COL2의 문자 길이를 생각하지 않고 50 이하 문자길이로 생성 할 때 발생되는 차이점
VARCHAR는 가변 길이 문자열이라 데이터 저장 시에는 실제 길이만큼 저장되지만, MySQL 내부에서는 records[2]라는 메모리 버퍼를 테이블 최대 컬럼 크기에 맞춰 한 번 할당해서 여러 연결에서 공유한다.
따라서, 실제 저장할 문자열 길이를 고려해 최대 길이 VARCHAR(n)를 적절히 설정하는 것이 메모리 사용 측면에서 더 효율적이다.
즉, 불필요하게 큰 크기로 설정하면 records[2] 버퍼도 커져서 메모리 낭비가 발생할 수 있다.
CREATE TABLE tmp_tb ( col1 VARCHAR(30), //약 121 byte 메모리 할당 사용 col2 VARCHAR(255) //약 1021 byte 메모리 할당 사용 );