본문으로 건너뛰기

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_LENGTH SQL 모드가 활성화된 경우 제외)

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자 패딩)

4.4 공간 효율성 분석

4.4.1 VARCHAR가 유리한 경우

  • 짧은 문자열이 많은 경우: 이름, 제목 등
  • 길이가 다양한 경우: 설명, 주소 등
  • 빈 값이 많은 경우: 선택적 필드

4.4.2 CHAR가 유리한 경우

  • 고정 길이 데이터: 국가 코드(KR, US), 상태 코드
  • 길이가 거의 최대값에 근접: 해시값, UUID
  • 성능이 중요한 경우: 자주 조회되는 키 값

5. SQL 모드에 따른 처리

5.1 비엄격 모드 (Non-strict Mode)

strict SQL 모드가 비활성화된 경우:

  • CHAR 또는 VARCHAR 컬럼의 최대 길이를 초과하는 값이 할당되면, 값이 잘려서 저장됩니다
  • 경고 메시지가 생성됩니다
  • 공백이 아닌 문자가 잘릴 때도 경고만 발생하고 삽입은 진행됩니다

5.2 엄격 모드 (Strict Mode)

strict SQL 모드가 활성화된 경우:

  • 공백이 아닌 문자가 잘릴 경우 오류가 발생합니다
  • 값 삽입이 거부됩니다
  • 길이 초과 시 데이터가 저장되지 않습니다

5.3 후행 공백 처리

5.3.1 VARCHAR 컬럼

  • SQL 모드와 관계없이 컬럼 길이를 초과하는 후행 공백은 삽입 전에 잘립니다
  • 경고가 생성됩니다

5.3.2 CHAR 컬럼

  • SQL 모드와 관계없이 삽입된 값의 초과 후행 공백은 자동으로 잘립니다
  • 경고 없이 처리됩니다

6. 후행 공백 처리의 차이점

6.1 저장 시 동작

  • VARCHAR: 저장 시 패딩하지 않으며, 후행 공백이 유지됩니다
  • CHAR: 지정된 길이에 맞춰 우측에 공백으로 패딩됩니다

6.2 검색 시 동작

  • VARCHAR: 저장된 후행 공백이 그대로 반환됩니다
  • CHAR: 후행 공백이 제거되어 반환됩니다 (PAD_CHAR_TO_FULL_LENGTH SQL 모드가 활성화된 경우 제외)

6.3 실제 예시

-- 테이블 생성
CREATE TABLE vc (v VARCHAR(4), c CHAR(4));

-- 후행 공백이 있는 데이터 삽입
INSERT INTO vc VALUES ('ab ', 'ab ');

-- 결과 확인
SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;

결과:

+---------------------+---------------------+
| CONCAT('(', v, ')') | CONCAT('(', c, ')') |
+---------------------+---------------------+
| (ab ) | (ab) |
+---------------------+---------------------+

VARCHAR는 후행 공백을 유지하지만, CHAR는 검색 시 후행 공백이 제거됩니다.

7. 콜레이션과 패딩 속성

7.1 문자열 정렬과 비교

  • CHAR, VARCHAR, TEXT 컬럼의 값들은 해당 컬럼에 할당된 문자 집합 콜레이션에 따라 정렬되고 비교됩니다.

7.2 PAD_ATTRIBUTE 속성

  • MySQL의 모든 콜레이션은 PAD_ATTRIBUTE라는 속성을 가지며, 이 속성에는 두 가지 값이 있습니다:
  • PAD SPACE
    • 대상: 대부분의 콜레이션 (기본값)
    • 동작: 문자열 비교 시 후행 공백을 무시
    • 예시: 'hello' = 'hello 'true (같다고 판단)
  • NO PAD
    • 대상: UCA 9.0.0 이상 기반 유니코드 콜레이션
    • 동작: 문자열 비교 시 후행 공백을 의미 있는 문자로 취급
    • 예시: 'hello' = 'hello 'false (다르다고 판단)

7.3 PAD_ATTRIBUTE 속성 확인

  • 콜레이션의 패드 속성을 확인하려면 INFORMATION_SCHEMA.COLLATIONS 테이블의 PAD_ATTRIBUTE 컬럼을 사용합니다.
-- 콜레이션의 PAD_ATTRIBUTE 속성 확인
SELECT COLLATION_NAME, PAD_ATTRIBUTE
FROM INFORMATION_SCHEMA.COLLATIONS
WHERE COLLATION_NAME = 'utf8mb4_general_ci';
SQL 모드의 영향

서버 SQL 모드는 후행 공백과 관련된 비교 동작에 영향을 주지 않습니다.

8. 특수 상황

8.1 InnoDB의 대용량 CHAR 필드 최적화

  • InnoDB는 768바이트 이상의 고정 길이 필드를 가변 길이 필드로 인코딩하여 오프페이지에 저장할 수 있습니다.
  • 예시:
    • utf8mb4 문자 집합에서 CHAR(255) 컬럼
    • 문자 집합의 최대 바이트 길이가 3보다 큰 경우 (utf8mb4는 4바이트)
    • 255 × 4바이트 = 1,020바이트로 768바이트를 초과
    • 이 경우 InnoDB가 내부적으로 최적화를 적용
InnoDB 최적화

대용량 CHAR 필드는 실제로는 가변 길이처럼 처리되어 성능과 공간 효율성이 개선됩니다.

8.2 인덱스와 중복 키 오류

  • 후행 패드 문자가 제거되거나 비교에서 무시되는 경우 인덱스와 중복 키 오류가 발생합니다.
  • 유니크 인덱스가 있는 컬럼에서 후행 패드 문자 수만 다른 값을 삽입하면 중복 키 오류가 발생합니다
  • 예를 들어, 테이블에 'a'가 있을 때 'a ' (후행 공백 포함) 삽입 시 중복 키 오류가 발생합니다.

참고