# CHAR / VARCHAR

문자열을 사용할 때 `VARCHAR`만 사용하는 경우도 있지만, 모든 DBMS에서 두 타입으로 구분해서 제공하는 만큼 각각의 특징을 잘 이해하고 사용하는 것이 중요하다.

## 저장 공간

`CHAR`와 `VARCHAR`의 가장 큰 차이는 고정 길이냐 가변 길이냐의 차이이다.

* 고정 길이(`CHAR`): 실제 입력되는 컬럼값의 길이에 따라 사용하는 저장 공간의 크기가 변하지 않음
* 가변 길이(`VARCHAR`): 최대로 저장할 수 있는 길이가 제한되어 있지만, 그 이하 크기 값이 저장되면 그 만큼만 저장 공간을 사용
  * 추가적으로 유효 크기를 저장하기 위한 1-2바이트 공간이 필요(255바이트 이하 -> 1바이트, 255바이트 초과 -> 2바이트)

이렇게 보면 1바이트의 차이만 나기 때문에 항상 `VARCHAR`를 사용하는 것이 좋을 것 같지만, 아래 두 가지 판단 기준으로 `CHAR`를 사용하는 것이 더 효율적일 수 있다.

* 저장되는 문자열의 길이가 대부분 비슷한 경우
* 컬럼의 값이 자주 갱신되는 경우

### 자주 갱신되는 경우의 성능

자주 갱신되는 경우 `CHAR`가 더 나은 성능을 보이는데, 각 타입별 업데이트 방식이 다음과 같기 때문이다.

* `VARCHAR`의 경우 저장되는 문자열의 길이가 달라지는 경우 디스크에 할당된 공간을 재할당 후 이전에 사용했던 공간을 해제하는 디스크에 대한 I/O 작업
* `CHAR`의 경우 저장되는 문자열의 길이가 달라지더라도 레코드가 물리적으로 저장되는 위치가 변하지 않기 때문에 디스크 I/O 작업이 발생하지 않음

## VARCHAR 저장 공간 변경 주의사항

VARCHAR의 저장 공간을 변경하는 경우 작업에 따라 매우 빠르게 처리되기도 하지만, 특수한 경우에는 읽기 잠금을 걸고 레코드 복사 작업이 필요하기 때문에 시간이 오래 걸릴 수 있다.

* `VARCHAR` 길이 저장의 필요 저장 공간은 255바이트까지는 1바이트, 그 이상은 2바이트가 필요
* 문자당 4바이트를 사용하는 문자셋(예: `utf8mb4`)을 사용하는 경우, `VARCHAR(64)`부터는 최대 256바이트(64 \* 4)가 되어 2바이트가 필요

`VARCHAR(60)` 컬럼을 `VARCHAR(63)`으로 변경하는 경우와 `VARCHAR(64)`로 변경하는 경우의 예시를 살펴보면 다음과 같다.

* `VARCHAR(63)`으로 변경하는 경우
  * INPLACE 알고리즘으로 처리되어 잠금 없이 매우 빠르게 처리
* `VARCHAR(64)`로 변경하는 경우
  * 1바이트에서 2바이트로 유효 크기 저장 공간 크기 변경 필요
  * 테이블의 모든 행을 COPY 알고리즘으로 처리되어 읽기 잠금을 걸고 레코드 복사 작업 수행

**참고자료**

* [Real MySQL 8.0 (2권)](https://kobic.net/book/bookInfo/view.do?isbn=9791158392727)
