부트캠프 팀과제5 TIL

백엔ㄷ현·2024년 8월 23일

나의 발표내용

VARCHAR vs TEXT

개요

MySQL 서버를 포함한 RDBMS를 사용하다 보면, No-SQL DBMS 서버에 비해서 많은 데이터 타입들을 가지고 있다. 하지만 RDBMS를 사용하면서 이런 다양한 데이터 타입에 대해서 정확한 용도와 특성을 모르면 RDBMS 서버가 어렵게 구현하고 있는 장점을 놓쳐 버릴 가능성이 높게 된다.


많은 개발자와 DBA들이 잘 모르고 있는 MySQL 서버의 VARCHAR 와 TEXT 타입의 특성과 작동 방식에 대해 요약을 해보았다.

VARCHAR 타입 궁금증

만약 10 글자 이하로만 저장된다면 컬럼의 타입을 VARCHAR(10)으로 하거나 VARCHAR(1000)으로 해도 아무런 차이가 없는 것 아닐까?

오히려 VARCHAR(1000)으로 만들어 두면 나중에 더 큰 값을 저장해야 할 때 더 유연하게 대응할 수 있지 않을까 ?

MySQL 서버가 내부적으로 어떻게 작동하는지를 모르면, 이 질문에 명확한 답변을 하기는 어려울 수 있다.

-- 1.
mysql> CREATE TABLE tb_long_varchar (id INT PRIMARY KEY, fd1 VARCHAR(1000000));
ERROR 1074 (42000): Column length too big for column 'fd1' (max = 16383); use BLOB or TEXT instead
-- 2.
mysql> CREATE TABLE tb_long_varchar (id INT PRIMARY KEY, fd1 VARCHAR(16383));
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
-- 3.
mysql> CREATE TABLE tb_long_varchar (id INT PRIMARY KEY, fd VARCHAR(16382));
Query OK, 0 rows affected (0.19 sec) 
-- 4.
mysql> ALTER TABLE tb_long_varchar ADD fd2 VARCHAR(10);
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

tb_long_varchar 테이블은 하나의 VARCHAR 컬럼이 있는데, VARCHAR 타입의 최대 저장 가능 길이를 어느 정도로 하느냐에 따라서 테이블을 생성하지 못하게 되는 것을 확인할 수 있다.

그리고 네번째 ALTER TABLE 문장의 실행 예제를 보면, 새로운 컬럼 추가가 실패한 것을 알 수 있다. 이는 (에러 메시지에서도 잘 설명하고 있듯이) 이미 tb_long_varchar 테이블은 하나의 레코드가 저장할 수 있는 최대 길이가 65,535 바이트를 초과했기 때문에 더이상 새로운 컬럼을 추가할 수 없게 된 것이다.

이 예제를 통해서 MySQL 서버에서는 하나의 VARCHAR 컬럼이 너무 큰 길이를 사용하면, 다른 컬럼들이 사용할 수 있는 최대 공간의 크기가 영향을 받게 된다는 것을 확인할 수 있다. 그래서 MySQL 서버에서는 레코드 사이즈 한계로 인해서, VARCHAR 타입의 최대 저장 길이 설정시에 공간을 아껴서 설정해야 한다.

그런데 VARCHAR 타입의 길이 설정에 주의해야 하는 이유가 이거 하나 뿐일까? 예를 들어서 추가로 새로운 컬럼이 필요치 않아서 아래와 같이 테이블을 모델링했다면, 이건 아무 문제가 없는 것일까 ?

CREATE TABLE user (
  id       BIGINT NOT NULL,
  name     VARCHAR(4000),
  phone_no VARCHAR(4000),
  address  VARCHAR(4000),
  email    VARCHAR(4000),
  PRIMARY KEY(id)
);



TEXT 타입 궁금증

그런데 VARCHAR 대신 TEXT 타입을 사용하면 길이 제한 문제가 싹 사라진다는 것을 쉽게 확인할 수 있다.

그래서 아래와 같이 테이블을 만들면 VARCHAR 타입의 길이 설정에 대한 제약뿐만 아니라 저장하는 값의 길이 제한도 훨씬 크고 유연하게 테이블을 만들 수 있다.

  CREATE TABLE user (
  id       BIGINT NOT NULL,
  name     TEXT,
  phone_no TEXT,
  address  TEXT,
  email    TEXT,
  PRIMARY KEY(id)
);

문자열 저장용 컬럼을 생성할 때, VARCHARTEXT 중에서 굳이 VARCHAR를 선택할 이유가 있을까 ? TEXT 타입은 저장 가능 길이도 훨씬 크고 테이블 생성할 때 굳이 길이 제한을 결정하지 않아도 되니 더 좋은 것 아닐까 ? 근데 왜 우리가 모델링하는 테이블에서 대부분 문자열 저장용 컬럼은 TEXT 컬럼이 아니라 VARCHAR 컬럼이 사용될까 ?

VARCHAR vs TEXT

RDBMS TEXT 같은 대용량 데이터를 저장하는 컬럼 타입을 LOB(Large object) 타입이라고 한다. 그리고 RDBMS LOB 데이터를 off-page라고 하는 외부 저장 공간에 저장을 한다.

MYSQL 서버도 b-tree라고 하는 곳에 저장을 하지만 용량이 큰, 길이가 길어서 저장 공간이 많이 필요한 경우에만 LOB 데이터는 똑같이 off-page 에 저장을 하게 된다.

MYSQL 서버는 uchar* records[2] 라는 메모리 포인터를 이용해서 레코드 데이터를 주고 받는다. 이때 메모리 객체는 실제 레코드의 데이터 크기에 관계 없이 최대 크기로 메모리를 할당해준다.

varchar 타입은 최대 크기가 설정되기 때문에 메모리 공간을 records[2] 버퍼에 미리 할당 받아둘 수 있지만, text 타입은 실제 최대 크기만큼 메모리를 할당해 두면 메모리 낭비가 너무 심해지는 문제가 발생한다.

그래서 records[2] 포인터가 가리키는 메모리 공간은 varchar 는 포함하지만 text 컬럼을 위한 공간은 포함하지 않게 된다.

즉, records[2] 메모리 버퍼는 처음 한번 할당되면 많은 컨넥션들에 의해서 재사용될 수 있도록 설계가 되어있는 것이다.

하지만 text를 위한 메모리 공간은 records[2]에 미리 할당되어 있지 않기 때문에 매번 레코드를 읽고 쓸 때마다 필요한 만큼 메모리가 할당되어야 한다.


컬럼 타입 선정 규칙

  • VARCHAR :
    • VARCHAR는 저장할 문자열의 최대 길이를 설정해야 하며, 해당 길이에 맞춰 메모리가 할당됨
    • 일반적으로 VARCHAR 타입은 길이가 상대적으로 짧은 문자열을 저장할 때 적합하며, 해당 컬럼이 자주 조회되는 경우 유리
    • 그러나 VARCHAR의 길이가 매우 길어지면, MySQL은 이 데이터를 B-Tree 외부의 공간(Off-Page)에 저장하게 되어 TEXT와 유사한 방식으로 동작할 수 있음

  • TEXT :
    • TEXT 타입은 문자열 데이터의 최대 길이를 설정하지 않고, 길이에 따라 메모리가 동적으로 할당됨.
    • 주로 길이가 긴 문자열이나 큰 데이터를 저장할 때 사용되며, 메모리 낭비를 줄일 수 있다.
    • 그러나 TEXT 컬럼은 매번 메모리를 할당하고 해제해야 하므로, 자주 조회되는 데이터라면 성능에 영향을 줄 수 있다.

  • 사용 시점 :
    VARCHAR는 상대적으로 짧은 문자열을 저장하거나 메모리가 충분할 때 유리
    TEXT는 길이가 긴 문자열 데이터를 저장해야 하거나 메모리 절약이 필요할 때 적합





profile
매일매일 공부한 내용과 코드 기록하겠습니다

0개의 댓글