[MySQL] VARCHAR vs TEXT

기훈·2024년 7월 9일

MySQL

목록 보기
17/23

공통점

  • 문자열 속성 값을 저장

  • 최대 65,535 Byres 까지 저장 가능

차이점

  • TEXT 타입 컬럼은 인덱스 생성 시 반드시 Prefix 길이 지정 필요 ( CREATE INDEX is_text_column ON table (text_column(100));

  • TEXT 타입 컬럼은 표현식으로만 디폴트 값 지정 가능 (CREATE TABLE tb1(col1 TEXT DEFAULT ('abc'))

일반적인 사용 형태

  • 길이가 짧으면 VARCHAR, 길이가 길면 TEXT 타입

  • VARCHAR 타입은 메모리 버퍼 공간을 미리 할당해 두며 재활용 가능 (하지만 VARCHAR도 너무 커지면 TEXT와 동일하게 동작한다) -> 컬럼 사용이 빈번하고 메모리 용량이 충분하면 이점을 가짐

  • TEXT는 그때 그때 필요할 때마다 할당 & 해제

Off-Page

  • MySQL 서버의 레코드 크기 제한은 65,535 바이트이지만, 스토리 엔진의 레코드 크기는 블록의 크기에 따라 달라지는데, 대부분 블록 절반의 절반이 스토리지 엔진의 크기 제한으로 작동한다. 즉 InnoDB 스토리지 엔진은 레코드의 전체 크기가 이 제한 사항(16KB 페이지에서는 8,117 바이트)을 초과하면 길이가 긴 컬럼을 선택해서 Off-Page로 저장하게 되는데, 이는 쿼리 처리 성능에 매우 큰 차이를 준다. (일반적으로 VARCHAR는 레코드, TEXT는 Off-Page로 저장된다)

  • 주의) VARCHAR도 크기가 매우 커지게 되면 Off-Page로 저장된다.

메모리 활용

  • MySQL 서버는 스토리지 엔진과 Handler API를 이용해서 데이터를 주고 받는데, 이때 MySQL 엔진과 InnoDB 스토리지 엔진은 uchar* records 메모리 포인터를 이용해서 레코드 데이터를 주고 받는다. records 메모리 객체는 실제 레코드의 데이터 크기에 관계 없이 최대 크기로 메모리를 할당한다. VARCHAR 타입은 최대 크기가 설정되기 때문에 메모리 공간을 records 버퍼에 미리 할당받아둘 수 있지만, TEXT나 BLOB와 같은 LOB 컬럼 데이터의 경우 실제 최대 크기만큼 메모리를 할당해 두면 메모리 낭비가 너무 심해지는 문제가 있다. 그래서 records 포인터가 가리키는 메모리 공간은 VARCHAR는 포함하지만 TEXT 컬럼을 위한 공간은 포함하지 않는다.

  • uchar* records 메모리 공간은 TABLE 구조체(struct) 내에 정의되어 있으며 TABLE 구조체는 MySQL 서버 내부에 캐싱되어서 여러 컨넥션에서 공유해서 사용될 수 있도록 구현되어 있다. 즉, records 메모리 버퍼는 처음 한번 할당되면 많은 컨넥션들에 의해서 재사용될 수 있도록 설계된 것이다.
    하지만 TEXT나 BLOB과 같은 LOB 컬럼을 위한 메모리 공간은 records에 미리 할됭되어 있지 않기 때문에 매번 레코드를 읽고 쓸 때마다 필요한 만큼 메모리가 할당되어야 한다.

  • VARCHAR 타입의 컬럼을 읽을 때는 새롭게 메모리를 할당받는 것이 아니라 TABLE 구조체의 records 버퍼를 이용해요. 하지만 TEXT나 BLOB와 같은 LOB 타입의 컬럼을 읽을 때는 (미리 할당해 둔 메모리 공간이 없기 때문에) 매번 필요한 크기만큼 메모리를 할당해서 사용후 해제해야 한다. LOB 컬럼의 값을 읽기 위해서 할당 및 해제하는 메모리 공간은 Performance_schema에 의해서 측정되지 않는다. (MySQL 8.0.33 기준) 그래서 LOB용 메모리 할당 해제가 실행되는지 알 수 없어서 성능 영향도를 파악하기가 어려운 상황이다.

  • 주의) 은 VARCHAR 타입에 저장된 값의 길이가 길어서 Off-Page로 저장된 경우, MySQL 서버는 TABLE 객체의 records 버퍼를 사용하지 못하고 새롭게 메모리 공간을 할당해서 사용해요. 그래서 VARCHAR 타입에 매우 큰 값이 빈번하게 저장되는 경우는 주의가 필요하다.

0개의 댓글