본문 바로가기
Database/MySQL

문자열을 저장할 때 CHAR, VARCHAR 선택 하기 위한 작은 팁

by oncerun 2024. 8. 10.
반응형

 

데이터베이스의 테이블을 설계할 때 문자열 컬럼의 타입을 정할 때 조금은 도움이 되지 않을까 이 글을 작성합니다.

 

VARCHAR와 CHAR 타입은 공통적으로 문자열을 저장하기 위한 타입으로 각 비즈니스 상황에 맞춰 정하게 됩니다.

 

각 타입의 옆에 존재하는 크기에 대해 가끔 바이트 크기로 착각하시는 분이 계시는데, 이는 바이트 크기가 아닌 문자열의 길이를 표현합니다.

 

문자열의 바이트는 사실 CHAR, VARCHAR 타입으로 지정된 컬럼의 문자셋에 영향을 받게 됩니다.

 

예를 들어 latin 문자셋을 사용하고 CHAR(10) 타입을 설정한 경우 각 문자 당 1바이트를 사용하여 최대 10바이트까지 사용될 수 있을 것입니다.

 

많이 사용하는 utf8mb4같은 경우는 최소 10바이트부터 최대 40바이트까지 사용할 수 있을 것입니다.

 

VARCHAR(10)을 할당하게 되면 문자 당 바이트를 문자셋에 따라 계산하여 꼭 필요한 공간만을 사용하게 되며 최대 40바이트를 넘지 못할 것입니다.

 

추가적으로 VARCHAR는 문자열의 길이를 저장하기 위해 특정 바이트를 사용합니다. 

0~255 길이를 갖는 경우 1바이트를 사용하며 그 이상은 2바이트를 할당합니다. 

 

CHAR 타입도 가변 문자셋을 사용하는 경우 문자열 길이를 저장하기 위해 바이트를 할당합니다.

 

 

CHAR

 

CHAR 타입은 고정된 문자열의 길이를 할당하여 문자열을 저장하게 됩니다.

 

따라서 고정된 길이인 경우 CHAR타입을 선택하는 경우가 있는데, 이 부분에 대해 약간은 고민할 거리가 있습니다.

 

이를 이야기하기 전 VARCHAR 타입을 사용하여 문자열 저장 컬럼을 지정한 경우 해당 컬럼이 자주 UPDATE 된다고 가정하고 이를 처리하는 과정에 대해 이야기해보겠습니다.

 

VARCHAR는 미리 공간을 예약해두지 않습니다. 해당 문자열 길이에 따라 딱 필요한 만큼의 공간을 할당해 저장합니다.

 

만약 해당 컬럼에 들어간 문자열보다 더 길이가 긴 문자열이 들어온 경우 어떻게 될까요?

 

이해를 돕기 위해 데이터 페이지에 대한 간단한 개념을 소개드립니다.

 

 데이터베이스에서 데이터를 저장하는 기본 단위는 데이터 페이지라고 합니다. 

이 데이터페이지 테이블의 행, 인덱스, 기타 DB 객체들이 저장됩니다. 

일반적으로 크기는 16KB의 크기를 가지며 이 안에 여러 레코드들이 저장됩니다.

이러한 데이터 페이지 관리는 실질적으로 데이터베이스 성능에 매우 중요한 역할을 하는데, 페이지 내에서 데이터 배치와 재배치는 쿼리 성능과 디스크 I/O에 직결되기 때문입니다.

 

VARCAHR의 특징에 따라 UPDATE 요청에 따른 기존보다 길이가 더 긴 문자열을 저장하기 위해 공간을 탐색하는 과정이 필요합니다. 기존의 값에 DELETE 마킹을 하고 새로운 자리에 새로운 값을 저장합니다.

 

만약 새로운 자리가 없다면 어떻게 될까요?

 

데이터페이지의 COMPACT 과정을 통해 자리를 만들고 해당 자리를 찾아서 새로운 값을 저장하게 될 것입니다.

 

만약 CHAR를 사용한다면 이 과정이 어떻게 개선될까요?

 

CHAR 타입이 고정된 길이의 문자열을 저장하기 때문에 업데이트 시 공간을 다시 할당하거나 데이터 페이지를 컴팩트하는 과정이 필요 없습니다. 

 

만약 해당 컬럼이 인덱스로 지정된 경우에는 인덱스의 일정한 크기로 유지되어 인덱스 검색, 정렬이 향상되고, 데이터 페이지 변경에 영향을 적게 주기 때문에 인덱스의 재구성 빈도를 감소시킵니다

 

 

이러한 상황을 고려하기 위해선 데이터의 조건이 영향을 미칩니다.

 

1. 설정된 문자열 길이에 대해 저장되는 데이터의 범위 폭이 작아야 합니다.

 

100의 길이를 지정한 경우 해당 데이터들은 90~100 사이의 길이를 가지는 경우 범위 폭이 좁다고 할 수 있습니다.

 

2. UPDATE가 빈번한 경우와 컬럼이 인덱스 된 경우

 

위에서 설명한 것과 같이 데이터 페이지의 컴팩트 과정이 적고, 고정된 길이를 가지고 있기에 VARCHAR보다 공간 효율성이 더 좋을 수 있습니다. 인덱스의 재구성 빈도도 더 적을 것입니다.

 

 

이제 우리는 문자열을 저장하기 위해 VARCHAR와 CHAR 타입을 선택할 때 한 번 더 고민하여 정할 수 있을 것입니다.

 

 

 

 

추가로 고민해 보면 좋을 것들.

 

 - 하나의 레코드가 저장할 수 있는 최대 바이트는 몇일까요?

 - LONGTEXT, BLOB이 속성이 많은 레코드에 포함될 때 어떤 영향을 줄 수 있을까요?

 

 

 

 

 

 

[참고] https://youtu.be/SdmQQPKnQRg?si=31xRHLTqjjkvABDj

 

 

 

 

 

 

 

반응형

'Database > MySQL' 카테고리의 다른 글

[MySQL] 트리거  (0) 2020.07.01
[MySQL] 커서  (0) 2020.07.01
[MySQL] Stored Program  (0) 2020.07.01
MySQL DATE / TIME TYPE  (0) 2020.05.09
MySQL String Type  (0) 2020.05.09

댓글