MySQL에서 문자열을 저장할 때 가장 많이 사용되는 두 가지 데이터 타입은 CHAR와 VARCHAR입니다.
둘은 공통점도 있지만, 저장 방식과 성능 면에서 중요한 차이점이 있습니다.
이번 글에서는 CHAR와 VARCHAR의 차이점을 살펴보고, 각각 언제 사용하는 것이 적절한지 알아보겠습니다.
CHAR와 VARCHAR
공통점
- 문자열 저장용 데이터 타입
- 최대 저장 가능 문자 길이를 명시
- 바이트가 아닌 문자 길이를 명시하는 것임
- VARCHAR(255)
- CHAR(255)
- 바이트가 아닌 문자 길이를 명시하는 것임
두 타입 모두 문자열 데이터를 저장하기 위해 사용되고, 최대로 저장할 문자 길이를 명시해서 사용합니다.
char와 varchar는 어떤 문자셋으로 정의되었는지에 따라 사용하는 저장 공간의 크기가 달라집니다.
최대 길이를 10으로 하는 경우, latin-1은 최대 10byte를 사용하지만, utf-8mb4의 경우 언어에 따라 10 ~ 40byte까지 사용 가능합니다.
차이점
varchar | char | |
저장 공간 할당 | 저장되는 문자 길이만큼 저장 공간 할당 | 문자 길이에 관계없이 고정 크기 할당 |
최대 저장 길이 | 최대 16,383자 (65,535 바이트) | 최대 255자 |
값의 길이 관리 | 저장된 문자열의 길이 관리 (1 ~ 2byte) | 저장된 문자열의 길이 관리 X (utf-8mb4와 같은 가변길이 문자셋을 사용하는 경우 길이를 관리) |
고정 길이 문자셋과 가변 길이 문자셋
문자열 데이터를 저장할 때는 데이터 타입뿐만 아니라 문자셋에 따라서도 저장 방식이 달라질 수 있기 때문에 문자셋에 대한 이해가 필요합니다.
문자셋은 문자열이 차지하는 저장 공간에 따라 고정 길이 문자셋과 가변 길이 문자셋으로 분류할 수 있습니다.
고정 길이 문자셋의 경우 모든 문자열이 동일한 크기의 저장 공간을 차지합니다. 반면, 가변 길이 문자셋은 각 문자가 가변적인 바이트 수를 사용하며, 문자열의 실제 길이에 따라 저장 공간이 달라지게 됩니다.
고정 길이 문자셋 | 가변 길이 문자셋 | |
문자 크기 | 항상 일정 | 1~4byte 가변 |
저장 공간 | 빈 공간을 가지므로 더 큼 | 필요한만큼만 저장하므로 더 작음 |
읽기 속도 | 고정된 오프셋을 사용해 빠름 | 오프셋 계산이 필요해 느림 (길이 저장용 바이트 사용) |
쓰기 속도 | 빠름 | 느림 |
인덱싱 성능 | 더 좋음 | 길이가 달라 인덱스 효율이 떨어질 수 있음 |
공간 효율성 | 짧은 데이터도 큰 공간을 차지하므로 비효율적 | 필요한만큼만 저장하므로 효율적 |
ex) | latin-1, utf32 | utf8-mb4 |
고정 길이 문자셋을 사용하는 경우
- CHAR : 선언된 크기만큼의 저장 공간을 사용, 나머지는 공백 문자를 저장
- VARCHAR : 사용하는만큼의 저장 공간을 사용하고, 문자열의 길이를 저장하기 위해 1byte를 추가로 사용
가변 길이 문자셋을 사용하는 경우
VARCHAR를 사용하는 경우 고정 길이 문자셋과 동작에 큰 차이가 없습니다.
하지만 CHAR를 사용하는 경우에는 주의할 점이 있는데요. 최대 저장 가능한 길이보다 부족한 공간의 크기를 byte를 기준으로 채운다는 점입니다.
첫 번째 CHAR의 경우, 최대 10글자의 문자열을 저장할 수 있습니다. 현재 "자바"라는 한글 두 글자를 저장하고 있기 때문에 각각은 3byte씩 공간을 차지하게 됩니다. 10글자를 저장하기 때문에 최대 40byte를 저장할 수 있으므로 34byte의 공백문자를 가진다고 생각할 수 있지만, 실제로는 10byte를 기준으로 3byte만큼의 공백문자만을 저장하게 됩니다.
두 번째 CHAR의 경우, 현재 "자바파이썬"이라는 5글자를 저장하고 있습니다. 각각은 3byte를 사용하므로 총 15byte를 사용하게 되고, 빈 공간은 할당되지 않습니다.
마지막으로 VARCHAR는 고정 길이 문자셋과 동일하게 사용하는 공간만을 할당받게 됩니다.
결론 : 그래서 어떤걸 써야 좋은데?
고정된 길이의 문자열을 저장하는 경우 CHAR 쓰면 되는거 아님?
이 말에 대해 좀 더 고민해보기 위해서는 고정 길이 문자셋과 가변 길이 문자셋을 사용할 때를 나누어서 생각해보면 좋을 것 같습니다.
고정 길이 문자셋을 사용할 때, CHAR와 VARCHAR를 사용하면 어떤 차이가 있을까요?
고정된 길이의 문자열을 저장한다고 가정할 때, VARCHAR는 CHAR보다 문자열의 길이를 저장하기 위한 1byte만을 추가로 사용할 뿐입니다. 전체 시스템을 고려했을 때 1byte 크기는 큰 문제가 되지 않으므로 고정된 길이의 문자열을 저장하는 경우 CHAR와 VARCHAR, 어느 것을 사용해도 서비스에 영향을 주지 않습니다.
하지만, 저장하려는 문자열 길이의 가변 폭이 큰 경우에는 VARCHAR를 사용하는 것이 좋습니다.
1~100의 길이를 가지는 문자열을 저장해야 되는 경우 CHAR을 사용하는 것은 불필요한 byte 낭비가 발생할 수 있습니다.
하지만, 비교적 가변 폭이 적은 문자열을 저장해야 하는 경우 CHAR을 사용하는 것은 고려해볼만 합니다.
VARCHAR의 데이터 수정 동작 방식
VARCHAR를 사용하는 경우 공간에 딱 맞게 저장 공간을 할당하게 됩니다. 그러므로 문자열의 길이가 길어지게 되면 기존에 할당되었던 저장공간을 사용하지 못하고 새로운 저장 공간을 할당받아 변경된 문자열을 저장하게 됩니다.
처음에는 변경된 데이터를 저장할 새로운 저장공간을 쉽게 찾을 수 있지만 데이터 변경이 잦아지게 되면 파편화가 계속하여 일어나고, 결국 컴팩션이 일어나 성능 저하가 발생하는 문제가 발생할 수 있습니다.
변경이 자주 일어나고 저장되는 문자열의 길이 차이가 크지 않은 경우 CHAR를 활용하자
CHAR은 VARCHAR와 다르게 고정된 길이로 할당되므로 VARCHAR와 달리 레코드를 저장할 공간을 찾는 비용이 줄어들 수 있습니다. 어느 정도 공간 낭비가 발생할 수는 있지만 문자열의 길이 차이가 크지 않다면 CHAR를 활용해볼 수 있을 것 같습니다.
참고 자료