Nullable 타입 — '거의 항상 성능에 해롭다'는 공식 경고의 이유
ClickHouse Nullable 타입 및 UDF(SQL/Executable) 공식 문서 종합 (웹 리서치, 2026) — ClickHouse 공식 문서(sql-reference/data-types/nullable, sql-reference/statements/create/function, sql-reference/functions/udf) ClickHouse 공식 문서 Nullable
이 모듈을 다 읽으면
- Nullable(T)이 내부적으로 별도의 마스크 파일을 추가로 유지한다는 것을 설명할 수 있다
- 공식 문서가 Nullable을 피하라고 권고하는 구체적 이유를 설명할 수 있다
clickhouse-learn-01에서 다룬 컬럼 지향 저장을 전제로, NULL 값을 표현해야 할 때 컬럼 하나만으로는 부족해 별도의 파일을 추가로 유지해야 하는 Nullable(T) 타입의 내부 구조와, 공식 문서가 명시적으로 경고하는 성능 트레이드오프를 정리한다.
내부 구조 — 값 파일 하나 + NULL 마스크 파일 하나
Nullable(T) 컬럼은 실제로 두 개의 파일로 저장된다 — 평소와 똑같이 값을 저장하는 일반 파일 하나와, 각 행이 NULL인지 아닌지를 1/0 플래그로 표시하는 별도의 마스크 파일 하나다. 이 마스크는 .null이라는 서브컬럼으로 직접 조회할 수도 있는데, 이는 전체 값 컬럼을 다 읽지 않고도 어떤 행이 NULL인지만 빠르게 확인하고 싶을 때 유용하다.
핵심 포인트
- Nullable(T)은 값을 저장하는 일반 파일 + NULL 여부를 1/0으로 표시하는 별도 마스크 파일, 이렇게 두 파일로 저장됨
- 마스크는 .null 서브컬럼으로 직접 조회 가능 — 값 전체를 안 읽고도 NULL 여부만 빠르게 확인 가능
공식 문서의 경고 — '거의 항상 성능에 부정적'
공식 문서는 'Nullable을 쓰면 거의 항상 성능에 부정적 영향을 준다'고 명시적으로 경고한다. 이유는 세 가지로 요약된다 — (1) 마스크 파일이 추가로 필요해 디스크 사용량이 늘고, (2) 쿼리 실행 시 값 파일과 마스크 파일을 둘 다 읽어야 해서 I/O가 늘며, (3) Nullable 컬럼은 인덱스로 쓸 수 없어 쿼리 플랜 최적화(프라이머리 인덱스 기반 프루닝 등)의 대상에서 빠진다는 제약이 있다.
핵심 포인트
- Nullable 사용은 '거의 항상 성능에 부정적' — 공식 문서의 명시적 경고
- 이유 3가지: 마스크 파일로 인한 추가 디스크 사용, 값+마스크 두 파일을 읽어야 하는 I/O 증가, Nullable 컬럼은 인덱스로 못 써 쿼리 최적화 대상에서 제외됨
대안 — 정말 필요한 경우에만, 그 외엔 센티널 값으로
공식 문서는 대안으로 진짜로 '값이 없다'는 것 자체가 의미 있는 정보인 경우에만 Nullable을 예약해서 쓰고, 그 외의 '선택적 필드' 용도로는 그냥 타입의 기본값이나 별도의 센티널 값(예: 숫자라면 -1이나 0, 문자열이라면 빈 문자열)을 쓰는 것을 권한다 — 이렇게 하면 마스크 파일 없이 일반 컬럼으로 인덱싱·최적화 혜택을 그대로 받을 수 있다. 즉 Nullable은 범용적인 '선택 필드' 표현 수단이 아니라, 정말로 결측을 구분해야 하는 좁은 상황에만 쓰는 예외적 선택으로 취급해야 한다는 게 핵심 지침이다.
핵심 포인트
- 공식 권고: 진짜 결측 자체가 의미 있는 경우에만 Nullable을 예약, 나머지는 기본값/센티널 값으로 대체
- 센티널 값을 쓰면 마스크 파일 없이 일반 컬럼으로 인덱싱·최적화 혜택을 그대로 유지 가능