pg_clickhouse v0.10: PostgreSQL에서 ClickHouse로 분석 쿼리를 투명하게 위임하는 FDW의 작동 방식
요약
OLTP는 PostgreSQL, OLAP은 ClickHouse. 두 데이터베이스를 모두 쓰는 팀이 흔히 부딪히는 문제는 쿼리 인터페이스의 이원화다. 분석 쿼리를 짤 때마다 ClickHouse 클라이언트를 열거나, 별도 파이프라인으로 데이터를 이관해야 한다.
pg_clickhouse는 이 경계를 없애는 PostgreSQL 익스텐션이다. PostgreSQL 안에서 CREATE FOREIGN TABLE로 ClickHouse 테이블을 외부 테이블로 등록하면, 이후의 SELECT는 PostgreSQL이 투명하게 ClickHouse SQL로 재작성해 실행하고 결과만 돌려준다.
2026년 7월에 릴리스된 v0.10.0은 다음을 가져왔다.
- TPC-H 22개 쿼리 중 완전 푸시다운 비율: 12개 → 16개
- 기존 바이너리 드라이버를 C 드라이버로 전면 교체 (동시성 버그 수정, 함수 커버리지 두 배)
- 서브쿼리 부분 푸시다운 지원 시작
- 집계 함수(aggregate) 푸시다운 목록 확장
왜 FDW인가
PostgreSQL Foreign Data Wrapper(FDW)는 외부 데이터 소스를 PostgreSQL 내부 테이블처럼 다루는 표준 확장 메커니즘이다. 사용자는 외부 데이터 소스를 의식하지 않고 표준 SQL을 작성한다. FDW 레이어가 그 SQL을 외부 소스에 맞게 변환·실행한다.
대부분의 FDW는 풀백(pullback) 방식이다. 외부 테이블에서 행을 전부 가져온 뒤 PostgreSQL 안에서 필터링과 집계를 수행한다. 수백만 행을 네트워크로 전송한 후 로컬에서 집계하는 셈이다.
pg_clickhouse는 푸시다운(pushdown) 방식을 극대화한다. PostgreSQL 플래너가 WHERE, GROUP BY, ORDER BY, HAVING 절을 FDW에 전달하면, pg_clickhouse가 이를 ClickHouse SQL로 변환해 ClickHouse 엔진에서 실행한다. PostgreSQL은 최종 결과만 받는다.
푸시다운 협상 메커니즘
PostgreSQL FDW 푸시다운은 단순히 "전부 보내거나, 전부 당기거나"가 아니다. 플래너와 FDW 사이의 협상(negotiation) 과정이다.
- 플래너가 FDW에 조건을 전달한다. "이
WHERE age > 30 AND country = 'KR'조건을 네가 처리할 수 있느냐?" - FDW가 비용 추정치를 반환한다. "처리 가능하다. 예상 행 수 1,000건, 비용 X."
- 플래너가 결정한다. FDW가 처리하는 경우의 전체 계획 비용 vs. 로컬 처리 비용을 비교해 선택한다.
pg_clickhouse는 이 협상에서 최대한 많은 조건을 수락한다. ClickHouse로 변환할 수 없는 함수나 표현식은 수락하지 않고 PostgreSQL이 처리하도록 남겨둔다.
쿼리 재작성 예시
-- PostgreSQL에 작성한 쿼리
SELECT country, SUM(amount) AS total
FROM ch_orders -- ClickHouse 외부 테이블
WHERE order_date >= '2026-01-01'
GROUP BY country
HAVING SUM(amount) > 100000
ORDER BY total DESC
LIMIT 10;pg_clickhouse가 ClickHouse로 전송하는 실제 쿼리:
-- ClickHouse에서 실행되는 쿼리
SELECT country, SUM(amount) AS total
FROM orders
WHERE order_date >= '2026-01-01'
GROUP BY country
HAVING SUM(amount) > 100000
ORDER BY total DESC
LIMIT 10WHERE, GROUP BY, HAVING, ORDER BY, LIMIT 전부 ClickHouse에서 실행된다. PostgreSQL은 10개 행만 받는다.
v0.10.0의 주요 변경사항
C 드라이버 전면 전환
v0.9까지는 ClickHouse 네이티브 프로토콜 통신에 기존 바이너리 드라이버를 사용했다. v0.10.0은 이를 새로운 순수 C 클라이언트 라이브러리로 교체했다.
이 전환의 실질적 효과:
- 동시성 버그 수정: 다중 연결 환경에서 드물게 발생하던 경쟁 조건 2건 해결
- 함수 커버리지 두 배: C 레이어 API 확장으로 이전에 PostgreSQL로 풀백됐던 집계 함수와 연산자 다수가 ClickHouse로 푸시다운 가능해짐
- DuckDB 등 다른 C 기반 드라이버 구조와 일관성: 향후 다른 분석 엔진 지원을 위한 코드 공유 가능성
TPC-H 푸시다운 확장
| 버전 | 완전 푸시다운 쿼리 수 (TPC-H 22개 중) |
|---|---|
| v0.8 이전 | 12개 |
| v0.10.0 | 16개 |
| 목표 | 22개 |
남은 6개 쿼리의 주요 장벽은 복잡한 서브쿼리 JOIN 트리다. PostgreSQL은 서브쿼리를 Anti/Semi Join으로 평탄화(flatten)한다. pg_clickhouse의 AST 번역기가 JOIN 트리 양측을 동시에 순회하는 기능이 아직 완전하지 않아 이 경우 ClickHouse로 위임하지 못한다.
서브쿼리 부분 지원
스칼라 서브쿼리와 단순 IN-서브쿼리 일부가 v0.10.0에서 처음으로 푸시다운된다. JOIN 기반 서브쿼리는 다음 릴리스의 주요 작업으로 남아 있다.
집계 함수 확장
ClickHouse 고유의 -If 접미 집계 함수(sumIf, countIf, avgIf 등)와 통계 집계(quantile, median 등) 다수가 v0.10에서 새로 지원됐다. 이 함수들이 포함된 쿼리에서 이전에는 행 전체가 PostgreSQL로 내려와 집계됐지만, 이제 ClickHouse에서 처리된 결과만 반환된다.
성능 벤치마크
TPC-H SF10 대표 쿼리 비교
| 쿼리 | 내용 | pg 없이 (순수 PG) | pg_clickhouse v0.10 | 배율 |
|---|---|---|---|---|
| Q1 | 집계 (lineitem 6천만 행) | 4,693ms | 268ms | 17.5× |
| Q3 | 조인 + 집계 | 742ms | 111ms | 6.7× |
| Q6 | 필터 + 집계 | 764ms | 53ms | 14.4× |
이 수치에서 "순수 PG"는 ClickHouse 없이 PostgreSQL에서만 실행하는 경우다. pg_clickhouse를 쓰면 ClickHouse의 컬럼형 엔진이 집계와 스캔을 담당하고 결과만 PostgreSQL로 전달되므로 속도 차이가 크게 벌어진다.
ClickBench 비교
pg_clickhouse는 PostgreSQL용 분석 익스텐션 중 ClickBench 기준 가장 빠른 익스텐션 위치에 있다. 네이티브 ClickHouse보다는 소폭 느린데, 오버헤드 원인은 세 가지다.
- 쿼리 재작성 시간 (보통 수 ms)
- 네트워크 왕복 시간 (LAN 환경 기준 1ms 이하)
- 결과를 PostgreSQL 형식으로 변환하는 시간
실제 운영에서 분석 쿼리의 대부분은 수 초 이상 걸리기 때문에 이 오버헤드는 무시할 수준이다.
운영 고려사항
설치와 설정
-- 익스텐션 설치
CREATE EXTENSION pg_clickhouse;
-- ClickHouse 서버 등록
CREATE SERVER ch_server
FOREIGN DATA WRAPPER clickhouse_fdw
OPTIONS (host 'clickhouse-host', port '9000');
-- 사용자 매핑
CREATE USER MAPPING FOR current_user
SERVER ch_server
OPTIONS (user 'default', password '');
-- 외부 테이블 등록
IMPORT FOREIGN SCHEMA default FROM SERVER ch_server INTO public;
-- 또는 개별 테이블 등록
CREATE FOREIGN TABLE ch_orders (...) SERVER ch_server OPTIONS (table 'orders');어떤 상황에 적합한가
적합한 경우:
- PostgreSQL 애플리케이션에서 ClickHouse의 분석 데이터에
SELECT쿼리가 필요할 때 - ClickHouse 클라이언트를 별도로 운영하지 않고 기존 PostgreSQL 연결로 OLAP 결과를 가져오려 할 때
- BI 도구가 PostgreSQL 연결만 지원하지만 ClickHouse 데이터가 필요할 때
적합하지 않은 경우:
- ClickHouse 데이터에 대한 대량
INSERT/UPDATE/DELETE가 필요한 경우 (DML 미지원) - 완전 pushdown이 필요한 복잡한 서브쿼리 (아직 6/22 TPC-H 미지원)
- 수천 건 이하의 소규모 OLTP 쿼리를 ClickHouse에 보내는 경우 (쿼리 재작성 오버헤드가 비효율)
동시성과 연결 관리
v0.9의 바이너리 드라이버는 동시 연결 수가 많을 때 간헐적 오류가 발생했다. v0.10.0의 C 드라이버가 이 문제를 수정했다. 그러나 ClickHouse 연결 수는 여전히 ClickHouse 서버의 max_connections 설정 안에서 관리해야 한다. PostgreSQL connection pool(pgBouncer 등)을 사용하는 환경에서는 FDW 연결이 session 모드에서만 올바르게 동작한다는 점도 확인이 필요하다.
로드맵: 남은 6개 TPC-H 쿼리
pg_clickhouse 팀이 밝힌 다음 단계:
- 서브쿼리 JOIN 트리 완성: PostgreSQL이 생성하는 Anti/Semi Join 패턴 전체를 AST 번역기가 처리할 수 있도록 deparser 확장
- 22/22 TPC-H 완전 커버: 남은 6개 쿼리의 푸시다운 완성
- 경량 DML 지원:
DELETE와UPDATE(ClickHouse lightweight delete/mutation) - ClickHouse 고유 타입 완전 지원: Tuple, Array, Map, Nested 타입
요점 정리
pg_clickhouse v0.10.0은 PostgreSQL과 ClickHouse 사이의 경계를 더 얇게 만들었다.
16/22 TPC-H 완전 푸시다운은 실용적인 분석 쿼리 대부분을 커버한다. C 드라이버 전환으로 동시성 안정성이 개선됐다. 서브쿼리와 집계 함수 지원 확장으로 이전에 PostgreSQL로 풀백되던 케이스가 줄었다.
ClickHouse를 이미 분석용으로 운영하면서 PostgreSQL 애플리케이션에서 접근이 필요한 팀에게 pg_clickhouse는 별도 ETL 없이 쿼리 하나로 분석 결과를 가져올 수 있는 실용적인 선택지다.
References
- ClickHouse 공식 블로그: "Introducing pg_clickhouse: A Postgres extension for querying ClickHouse"
https://clickhouse.com/blog/introducing-pg_clickhouse
- ClickHouse 공식 블로그: "What's new in pg_clickhouse v0.10.0: Subqueries, TPC-H Speedups, C Driver, and Aggregates"
https://clickhouse.com/blog/pg_clickhouse-whats-new-july-2026
- ClickHouse 공식 블로그: "pg_clickhouse is the fastest Postgres extension on ClickBench"
https://clickhouse.com/blog/pg_clickhouse-fastest-analytics-for-postgres
- ClickHouse 공식 블로그: "Postgres FDW: Pushdown is a negotiation"
https://clickhouse.com/blog/postgres-fdw-pushdown-negotiation
- GitHub: https://github.com/ClickHouse/pg_clickhouse
- PGXN: https://pgxn.org/dist/pg_clickhouse/
- pg_clickhouse 공식 문서: https://clickhouse.com/docs/products/managed-postgres/extensions/pg_clickhouse/introduction