Buffer 테이블 엔진 — 클라이언트가 직접 메모리 버퍼에 쓰는 대안
ClickHouse 병합 선택 알고리즘 및 Buffer 테이블 엔진 공식 문서 종합 (웹 리서치, 2026) — ClickHouse 공식 문서(merges, engines/table-engines/special/buffer) ClickHouse 공식문서 Buffer table engine
이 모듈을 다 읽으면
- clickhouse-learn-23의 async_insert(서버가 버퍼링)와 Buffer 테이블 엔진(별도 테이블 자체가 버퍼)의 구조적 차이를 설명할 수 있다
- min*/max* 플러시 조건의 조합 규칙과, 비정상 종료 시 데이터가 유실된다는 제약을 설명할 수 있다
clickhouse-learn-23에서 다룬 async_insert(서버 내부 메모리 버퍼)와 대비되는, 별도의 Buffer 엔진 테이블 자체를 버퍼로 두는 또 다른 소량 INSERT 완화 방식을 정리한다.
Buffer 엔진 — 쓰기용 테이블과 저장용 테이블을 분리한다
Buffer 테이블 엔진은 쓰기 데이터를 RAM에 버퍼링했다가, 주기적으로 다른(진짜 저장용) 테이블로 플러시하는 별도의 테이블 엔진이다. clickhouse-learn-23의 async_insert가 '서버가 내부적으로 알아서' 여러 INSERT를 모으는 방식이라면, Buffer 엔진은 애플리케이션이 명시적으로 Buffer 엔진 테이블을 만들어 거기에 쓰고, 그 Buffer 테이블이 조건에 따라 실제 대상 MergeTree 테이블로 데이터를 흘려보내는 구조다. 읽기 쿼리를 Buffer 테이블에 날리면 아직 플러시 안 된 버퍼 데이터와 이미 대상 테이블에 있는 데이터를 동시에 읽어 합쳐서 보여준다.
핵심 포인트
- Buffer 엔진: 쓰기 데이터를 RAM에 버퍼링 후 주기적으로 다른(대상) 테이블로 플러시하는 별도 테이블 엔진
- async_insert는 서버 내부에서 알아서 모으는 방식, Buffer 엔진은 애플리케이션이 명시적으로 그 버퍼 역할의 테이블을 따로 두는 방식
- Buffer 테이블 읽기 시 아직 플러시 안 된 버퍼 데이터 + 대상 테이블 데이터를 동시에 읽어 합산해 반환
플러시 조건 — min* 전부 충족 OR max* 하나라도 충족
Buffer 테이블은 min_time/max_time(첫 쓰기 이후 경과 시간), min_rows/max_rows(누적 행 수), min_bytes/max_bytes(데이터 크기) 세 축의 min/max 조건을 갖는다. 규칙은 'min* 조건을 전부 만족하거나, max* 조건 중 하나라도 만족하면' 버퍼를 플러시해 대상 테이블에 쓴다는 것이다 — min 조건은 '이 정도는 채워야 플러시할 가치가 있다'는 하한, max 조건은 '이 이상 쌓이면 지체 없이 무조건 플러시해야 한다'는 안전판 역할을 한다. 또한 num_layers로 버퍼를 여러 개의 독립된 레이어로 나눠 병렬 쓰기를 받을 수 있는데, 각 레이어마다 플러시 조건이 따로 계산된다(예: num_layers=16, max_bytes=100000000이면 최대 RAM 사용량은 1.6GB).
핵심 포인트
- 플러시 조건: min* 조건 전부 충족 OR max* 조건 중 하나라도 충족
- min_time/max_time·min_rows/max_rows·min_bytes/max_bytes 세 축, num_layers로 병렬 레이어 수 조절(레이어마다 조건 별도 계산)
치명적 제약 — 비정상 종료 시 버퍼 데이터가 통째로 사라진다
Buffer 테이블의 가장 중요한 주의점은, 서버가 비정상적으로 종료되면 아직 플러시되지 않은 버퍼 안의 데이터가 그대로 유실된다는 것이다(정상 종료 시에는 플러시가 트리거됨). 이는 clickhouse-learn-23에서 다룬 async_insert의 wait_for_async_insert=0(fire-and-forget) 모드가 갖는 내구성 트레이드오프와 근본적으로 같은 종류의 위험이다 — 두 방식 모두 '지연을 줄이는 대가로 서버 장애 시점의 데이터 유실 가능성'을 감수해야 하는 구조다. 그래서 Buffer 테이블은 안정성이 최우선인 데이터보다는, 유실을 감내할 수 있는 로그성 데이터의 인서트 완화 용도로 주로 쓰인다.
핵심 포인트
- 서버 비정상 종료 시 아직 플러시 안 된 버퍼 데이터는 통째로 유실(정상 종료 시엔 플러시됨)
- async_insert의 wait_for_async_insert=0과 근본적으로 같은 종류의 '지연 감소 vs 내구성' 트레이드오프 — 유실 감내 가능한 로그성 데이터에 주로 사용