CHAR-VARCHAR
1. CHAR와 VARCHAR 타입
- CHAR와 VARCHAR는 MySQL에서 문자열 데이터를 저장하는 가장 기본적이고 중요한 데이터 타입입니다.
- 두 타입은 문자열을 저장한다는 공통 점이 있지만, 저장 방식, 검색 방식, 메모리 사용량, 성능 특성에서 중요한 차이점을 보입니다.
1.1 핵심 차이점
- 저장 방식: CHAR는 고정 길이, VARCHAR는 가변 길이
- 공간 효율성: VARCHAR가 일반적으로 더 효율적
- 성능: CHAR가 특정 상황에서 더 빠를 수 있음
- 후행 공백 처리: 두 타입이 서로 다른 방식으로 처리
1.2 언제 사용하는가?
- CHAR: 고정 길이 데이터 (국가 코드, 상태 코드, 해시값 등)
- VARCHAR: 가변 길이 텍스트 (이름, 제목, 설명 등)
2. 기본 특성
2.1 선언 방식
- CHAR와 VARCHAR 타입은 저장하려는 문자의 최대 길이를 나타내는 숫자와 함께 선언됩니다.
- 이 숫자는 문자 개수를 의미하며, 바이트 수가 아닙니다.
- 한글과 같은 멀티바이트 문자의 경우, 하나의 문자 가 여러 바이트를 차지할 수 있습니다.
-- 기본 선언 방식
CHAR(길이) -- 고정 길이
VARCHAR(길이) -- 최대 길이
-- 구체적인 예시
CHAR(30) -- 정확히 30자, 항상 30자 공간 사용
VARCHAR(30) -- 최대 30자, 실제 길이만큼 공간 사용
VARCHAR(255) -- 최대 255자, 1바이트 길이 접두어 사용
VARCHAR(1000) -- 최대 1000자, 2바이트 길이 접두어 사용
2.2 문자 집합과 길이의 관계
- 사용하는 문자 집합(character set)에 따라 실제 저장 공간이 달라집니다.
-- UTF8MB4 문자 집합에서의 예시
CREATE TABLE example (
latin_char CHAR(10) CHARACTER SET latin1, -- 최대 10바이트
utf8_char CHAR(10) CHARACTER SET utf8mb4, -- 최대 40바이트
latin_varchar VARCHAR(100) CHARACTER SET latin1, -- 최대 100바이트
utf8_varchar VARCHAR(100) CHARACTER SET utf8mb4 -- 최대 400바이트
);
2.3 길이 제한
2.3.1 이론적 최대 길이
- CHAR: 0~255자까지 설정 가능
- VARCHAR: 0~65,535자까지 설정 가능
- 위는 어디까지나 이론적인 최대 길이입니다.
- VARCHAR의 실제 최대 길이는 최대 행 크기(65,535바이트)와 사용되는 문자 집합에 따라 제한됩니다.
- 모든 컬럼이 이 제한을 공유합니다.
2.3.2 실제 제한 사항
CREATE TABLE varchar_limit_test (
-- 이론적으로는 65,535자까지 가능하지만...
content VARCHAR(16383) CHARACTER SET utf8mb4 -- 실제 최대값
);
- 위는 UTF8MB4 문자 집합에서의 실제 제한을 보여주는 예시입니다.
- MySQL의 최대 행 크기: 65,535바이트
- UTF8MB4의 한 문자당 최대 바이트: 4바이트
- 길이 접두어: 2바이트 (255자 초과 시)
- 따라서 실제 최대 길이는 아래와 같이 계산됩니다.
(65,535 - 2) / 4 = 16,383
- 실제 최대 길이는 16,383자입니다.
2.3.3 다중 컬럼이 있는 경우
-- 여러 VARCHAR 컬럼이 있을 때의 제한
CREATE TABLE multiple_varchar (
col1 VARCHAR(10000) CHARACTER SET utf8mb4, -- 40,000바이트
col2 VARCHAR(6000) CHARACTER SET utf8mb4, -- 24,000바이트
col3 VARCHAR(400) CHARACTER SET utf8mb4 -- 1,600바이트
-- 총합: 65,600바이트 > 65,535바이트→ 오류 발생!
);
- 위는 여러 VARCHAR 컬럼이 있을 때의 제한을 보여주는 예시입니다.
- 최대 행 크기(65,535바이트)를 초과하므로 오류가 발생합니다.
3. 저장 방식의 차이
3.1 CHAR 타입의 저장 메커니즘
- CHAR 타입은 고정 길이 저장 방식을 사용합니다.
3.1.1 저장 과정
-- CHAR(10) 컬럼에 다양한 값 저장
CREATE TABLE char_example (name CHAR(10));
INSERT INTO char_example VALUES
('A'), -- 'A ' (9개 공백 추가)
('ABC'), -- 'ABC ' (7개 공백 추가)
('ABCDEFGHIJ'); -- 'ABCDEFGHIJ' (공백 추가 없음)
- 고정 길이: 선언된 길이로 고정 (항상 동일한 공간 사용)
- 저장 시: 지정된 길이에 맞춰 우측에 공백으로 패딩
- 검색 시: 기본적으로 후행 공백 제거 (
PAD_CHAR_TO_FULL_LENGTHSQL 모드가 활성화된 경우 제외)
3.2 VARCHAR 타입의 저장 메커니즘
- VARCHAR 타입은 가변 길이 저장 방식을 사용합니다.
3.2.1 저장 과정
-- VARCHAR(10) 컬럼에 다양한 값 저장
CREATE TABLE varchar_example (name VARCHAR(10));
INSERT INTO varchar_example VALUES
('A'), -- 길이 접두어(1) + 'A' = 2바이트
('ABC'), -- 길이 접두어(1) + 'ABC' = 4바이트
('ABCDEFGHIJ'); -- 길이 접두어(1) + 'ABCDEFGHIJ' = 11바이트
- 가변 길이: 실제 데이터 길이에 따라 저장 공간 결정
- 저장 방식: 길이 접두어 + 실제 데이터
- 공백 처리: 저장 시 패딩하지 않음, 후행 공백 유지
3.2.2 길이 접두어 시스템
- VARCHAR는 데이터 앞에 길이 정보를 저장합니다
- 255바이트 이하: 1바이트 길이 접두어 사용 (0~255 표현)
- 255바이트 초과: 2바이트 길이 접두어 사용 (0~65,535 표현)
-- 길이 접두어 예시
VARCHAR(100) -- 최대 100자, 1바이트 접두어 사용
VARCHAR(1000) -- 최대 1000자, 2바이트 접두어 사용
4. 저장 공간 비교
4.1 기본 비교 ( 단일 바이트 문자 집합)
- 다음 표는
CHAR(4)와VARCHAR(4)컬럼에 다양한 문자열 값을 저장했을 때의 결과를 보여줍니다 - latin1 등 단일 바이트 문자 집합 기준입니다.
| 값 | CHAR(4) | 저장 공간 | VARCHAR(4) | 저장 공간 | 공간 효율성 |
|---|---|---|---|---|---|
| '' | ' ' | 4바이트 | '' | 1바이트 | VARCHAR가 75% 절약 |
| 'ab' | 'ab ' | 4바이트 | 'ab' | 3바이트 | VARCHAR가 25% 절약 |
| 'abcd' | 'abcd' | 4바이트 | 'abcd' | 5바이트 | CHAR가 20% 절약 |
| 'abcdefgh' | 'abcd' | 4바이트 | 'abcd' | 5바이트 | CHAR가 20% 절약 |
문자열 잘림
마지막 행의 결과는 strict SQL 모드가 비활성화된 경우에만 적용됩니다. strict 모드에서는 컬럼 길이를 초과하는 값이 저장되지 않고 오류가 발생합니다.
4.2 UTF8MB4 문자 집합에서의 비교
한글을 포함한 UTF8MB4 환경에서의 저장 공간:
-- UTF8MB4 테스트 테이블
CREATE TABLE utf8_test (
char_col CHAR(10) CHARACTER SET utf8mb4,
varchar_col VARCHAR(10) CHARACTER SET utf8mb4
) CHARACTER SET utf8mb4;
INSERT INTO utf8_test VALUES
('안녕', '안녕'), -- 한글 2자
('Hello', 'Hello'), -- 영문 5자
('안녕하세요', '안녕하세요'); -- 한글 5자
| 값 | CHAR(10) 실제 저장 | 저장 공간 | VARCHAR(10) 저장 | 저장 공간 |
|---|---|---|---|---|
| '안녕' | '안녕' + 34바이트 패딩 | 40바이트 | '안녕' | 7바이트 (1+6) |
| 'Hello' | 'Hello' + 35바이트 패딩 | 40바이트 | 'Hello' | 6바이트 (1+5) |
| '안녕하세요' | '안녕하세요' + 25바이트 패딩 | 40바이트 | '안녕하세요' | 16바이트 (1+15) |
4.3 대용량 데이터에서의 비교
-- 대용량 TEXT 데이터 비교
CREATE TABLE large_text_test (
description VARCHAR(1000),
fixed_code CHAR(10)
);
-- 실제 저장 공간 계산
-- description에 100자 저장시: 2바이트(길이) + 100바이트 = 102바이트
-- fixed_code에 5자 저장시: 10바이트 (5자 + 5자 패딩)