Paimon 테이블 엔진
Paimon 테이블 엔진
이 엔진은 Amazon S3, Azure, HDFS 및 로컬에 저장된 기존 Apache Paimon 테이블과의 읽기 전용 통합을 제공해요. 스냅샷 읽기, 증분 읽기, 엔진이 제공하는 기본 파티션 가지치기(partition pruning)를 지원해요.
출처: 문서
본문
테이블 생성하기
Paimon 테이블이 이미 스토리지에 존재해야 한다는 점을 유의해요. 이 명령은 새 테이블을 만들기 위한 DDL 매개변수를 받지 않아요. Paimon* 테이블 생성은 allow_experimental_paimon_storage_engine(기본 비활성화) 뒤에 있으므로 CREATE TABLE을 실행하기 전에 활성화해요.
SET allow_experimental_paimon_storage_engine = 1;
CREATE TABLE paimon_table_s3
ENGINE = PaimonS3(url, [, access_key_id, secret_access_key] [,format] [,compression])
CREATE TABLE paimon_table_azure
ENGINE = PaimonAzure(connection_string|storage_account_url, container_name, blobpath, [,account_name], [,account_key] [,format] [,compression_method])
CREATE TABLE paimon_table_hdfs
ENGINE = PaimonHDFS(path_to_table, [,format] [,compression_method])
CREATE TABLE paimon_table_local
ENGINE = PaimonLocal(path_to_table, [,format] [,compression_method])
엔진 인자
인자에 대한 설명은 S3, AzureBlobStorage, HDFS, File 엔진의 인자 설명과 각각 일치해요. format은 Paimon 테이블의 데이터 파일 형식을 의미해요. 엔진 매개변수는 Named Collections로 지정할 수도 있어요.
예시
CREATE TABLE paimon_table ENGINE=PaimonS3('http://test.s3.amazonaws.com/clickhouse-bucket/test_table', 'test', 'test')
named collections 사용:
<clickhouse>
<named_collections>
<paimon_conf>
<url>http://test.s3.amazonaws.com/clickhouse-bucket/</url>
<access_key_id>test</access_key_id>
<secret_access_key>test</secret_access_key>
</paimon_conf>
</named_collections>
</clickhouse>
CREATE TABLE paimon_table ENGINE=PaimonS3(paimon_conf, filename = 'test_table')
Capabilities
- 최신 테이블 스냅샷에서 스냅샷 읽기
- 활성화되면 커밋된 스냅샷 id 기반 증분 읽기
use_paimon_partition_pruning이 활성화되면 파티션 가지치기- 구성되면 메타데이터의 선택적 백그라운드 새로고침
- Atomic/Replicated 데이터베이스 사용 시 안정적인 테이블 UUID로 Keeper 경로에서
{uuid}매크로 활성화
설정
이 엔진은 해당 객체 스토리지 엔진과 같은 설정을 사용하고 Paimon 고유 설정을 추가해요.
allow_experimental_paimon_storage_engine—Paimon,PaimonS3,PaimonAzure,PaimonHDFS,PaimonLocal테이블 엔진 생성을 활성화해요. 기본값:0(비활성화)use_paimon_metadata_files_cache— Paimon 메타데이터 파일 캐시를 활성화해요 (역직렬화된 manifest 목록과 manifest를 캐시).1로 설정해 활성화,0으로 비활성화. 기본값:0. 이 설정이 적용되는 방식은 테이블 함수와 영구 테이블 엔진 사이에서 다르데요 — 아래 참고를 보세요paimon_incremental_read— 증분 읽기 모드를 활성화해요paimon_metadata_refresh_interval_sec— 백그라운드 메타데이터 새로고침 간격(초). 0보다 큰 값으로 설정하면 백그라운드 작업이 객체 스토리지에서 최신 스냅샷과 스키마를 주기적으로 가져와요. 기본값: 30paimon_keeper_path— 증분 읽기 상태의 Keeper 경로. 테이블마다 설정되어 있어야 하고 고유해야 해요.{database},{table},{uuid}같은 매크로를 지원해요paimon_replica_name— 증분 읽기 상태의 복제본 이름. 복제본마다 설정되어 있어야 하고 고유해야 해요.{replica}같은 매크로를 지원해요
예시 (실험적 Paimon 엔진과 메타데이터 파일 캐시 활성화):
SET allow_experimental_paimon_storage_engine = 1;
SET use_paimon_metadata_files_cache = 1;
CREATE TABLE paimon_cached
ENGINE = PaimonS3(paimon_conf, filename = 'paimon_all_types');
use_paimon_metadata_files_cache가 적용되는 방식은 Paimon 테이블에 접근하는 방식에 따라 달라져요.
- 테이블 함수 (예:
SELECT ... FROM paimonS3(...)): 캐시 결정은 쿼리마다 평가되므로SELECT에서 직접SETTINGS use_paimon_metadata_files_cache = 1을 전달할 수 있어요 - 영구 테이블 엔진 (
PaimonS3,PaimonAzure,PaimonHDFS,PaimonLocal,Paimon별칭): 캐시 결정은 테이블 메타데이터가 초기화될 때 한 번 고정(latching)되어 불변의 영구 구성 요소에 저장돼요. 메타데이터 업데이트 경로는 의도적으로 설정을 다시 읽지 않아요. 따라서 이미 초기화된 영구 테이블에 대한SELECT에서SETTINGS use_paimon_metadata_files_cache = 1을 전달해도 효과가 없어요 — 앞서 고정된 결정이 계속 사용돼요. 바꾸려면 테이블의 메타데이터가 초기화되기 전에use_paimon_metadata_files_cache를 설정하거나, 원하는 값으로 테이블을DROP하고 다시CREATE해요
서버 레벨 캐시 용량(paimon_metadata_files_cache_size)은 고정되지 않아요: 이는 SYSTEM RELOAD CONFIG로 변경할 수 있는 런타임 설정이며, 이미 초기화된 테이블에도 즉시 적용돼요.
증분 읽기 예시
Keeper 상태와 함께하는 증분 읽기:
CREATE TABLE paimon_inc
ENGINE = PaimonS3(paimon_conf, filename = 'paimon_all_types')
SETTINGS
paimon_incremental_read = 1,
paimon_keeper_path = '/clickhouse/{database}/{uuid}',
paimon_replica_name = '{replica}';
증분 읽기용 쿼리 레벨 설정
다음 설정은 쿼리 레벨(CREATE TABLE이 아닌 SELECT ... SETTINGS로 전달)이에요. 증분 읽기의 쿼리별 동작을 제어해요.
paimon_target_snapshot_id— 지정된 스냅샷의 델타만 읽어요. Keeper의 커밋된 워터마크는 전진하지 않으므로 같은 스냅샷을 몇 번이든 다시 읽을 수 있어요. 기본값:-1(비활성화)max_consume_snapshots— 단일 증분 읽기에서 소비할 최대 스냅샷 수. 소스에 읽지 않은 스냅샷이 많이 쌓이면 이 값이 배치 크기를 제어하기 위해 쿼리당 소비 수를 제한해요.0은 제한 없음. 기본값:0
대상 스냅샷 읽기 — 현재 워터마크와 관계없이 항상 스냅샷 1의 델타를 반환해요.
SELECT count()
FROM paimon_inc
SETTINGS paimon_target_snapshot_id = 1;
배치당 스냅샷 제한 — 새 스냅샷 3개가 대기 중이면 쿼리당 최대 2개 소비:
SELECT count()
FROM paimon_inc
SETTINGS max_consume_snapshots = 2;
Refreshable Materialized View를 통한 Paimon에서 MergeTree로
APPEND 모드의 refreshable Materialized View를 사용해 Paimon 테이블의 데이터를 MergeTree 테이블로 지속적으로 동기화하는 종단 간 파이프라인을 구축할 수 있어요. 각 새로고침 주기는 Paimon에서 새 증분 데이터만 읽어 대상 테이블에 추가해요.
1단계 — 증분 읽기와 메타데이터 새로고침이 활성화된 Paimon 소스 테이블 생성.
아래 예시는 PaimonLocal을 사용해요. 스토리지 백엔드에 맞게 엔진을 PaimonS3, PaimonAzure, PaimonHDFS, 또는 자동 감지 Paimon 엔진으로 바꿔요.
SET allow_experimental_paimon_storage_engine = 1;
-- Local storage
CREATE TABLE paimon_mv_source
ENGINE = PaimonLocal('/path/to/paimon/table')
SETTINGS
paimon_incremental_read = 1,
paimon_keeper_path = '/clickhouse/tables/{uuid}',
paimon_replica_name = '{replica}',
paimon_metadata_refresh_interval_sec = 1;
-- S3 storage (the `Paimon` engine defaults to the S3 implementation when no `disk` is specified)
CREATE TABLE paimon_mv_source
ENGINE = Paimon('http://minio:9000/bucket/path/to/table', 'access_key', 'secret_key')
SETTINGS
paimon_incremental_read = 1,
paimon_keeper_path = '/clickhouse/tables/{uuid}',
paimon_replica_name = '{replica}',
paimon_metadata_refresh_interval_sec = 1;
paimon_metadata_refresh_interval_sec은 백그라운드 메타데이터 새로고침 간격(초)을 설정해요. 0보다 크면 백그라운드 작업이 객체 스토리지에서 최신 스냅샷과 스키마를 주기적으로 가져와서 MV 새로고침 주기가 쿼리가 메타데이터 업데이트를 트리거할 때까지 기다리지 않고 새로 커밋된 데이터를 볼 수 있게 해요. 기본값은 30. 많은 테이블에서 과도한 객체 스토리지와 Keeper I/O를 피하기 위해 주의해서 사용해요.
2단계 — MergeTree 대상 테이블 생성 (Paimon 테이블에서 스키마 복제):
CREATE TABLE paimon_mv_dest AS paimon_mv_source
ENGINE = MergeTree()
ORDER BY tuple();
3단계 — refreshable Materialized View 생성:
CREATE MATERIALIZED VIEW paimon_mv
REFRESH EVERY 10 SECOND
APPEND
TO paimon_mv_dest
AS SELECT * FROM paimon_mv_source;
10초마다 MV는 SELECT * FROM paimon_mv_source를 발사하고, 이는 마지막으로 커밋된 스냅샷 이후 추가된 행만 반환하여 paimon_mv_dest에 추가해요.
정리(Cleanup):
SYSTEM STOP VIEW paimon_mv;
DROP VIEW IF EXISTS paimon_mv SYNC;
DROP TABLE IF EXISTS paimon_mv_dest SYNC;
DROP TABLE IF EXISTS paimon_mv_source SYNC;
MV를 삭제하기 전에 중지시켜 백그라운드 새로고침이 DDL 연산을 차단하지 않게 해요.
제한 사항
- 증분 읽기는 Keeper(ZooKeeper)가 구성되어 있어야 해요
- 증분 읽기는
paimon_keeper_path가 설정되어 있어야 하고 테이블마다 고유해야 해요 paimon_replica_name은 같은 Keeper 경로 안에서 복제본마다 고유해야 해요- 증분 읽기는 최대 한 번(at-most-once) 전달을 사용해요: 데이터가 실제로 소비되기 전에 데이터 파일이 수집될 때 커밋된 스냅샷이 전진해요. 파일 수집 후 쿼리가 실패하면 건너뛴 스냅샷은 재시도 시 다시 읽히지 않아요
- 테이블 엔진은 읽기 전용이에요. 데이터 수정은 지원되지 않아요
- 증분 읽기는 Paimon 소스의 과거 데이터 삭제를 처리하지 않아요. 업스트림 Paimon 데이터가 삭제되거나 업데이트되면 이미 ClickHouse MergeTree 대상 테이블에 쓰인 해당 행은 자동으로 제거되지 않아요. 오래된 데이터를 정리하려면 MergeTree 테이블에서 수동으로
ALTER TABLE ... DELETE를 실행해야 해요 - 기본 Paimon 테이블이 같은 객체 스토리지 경로에서 삭제·재생성되면(예: Flink나 Spark를 통해) 해당 ClickHouse 테이블을
DROP하고 다시CREATE해야 해요. ClickHouse는 schema-0 생성 타임스탬프를 비교해 재생성을 감지하고 오류를 발생시켜요. 오래된 ClickHouse 테이블은 재생성 전까지 사용할 수 없어요
별칭(Aliases)
Paimon 테이블 엔진은 disk 설정에서 스토리지 백엔드를 자동으로 감지해 PaimonS3, PaimonAzure, PaimonLocal로 각각 배포해요. disk가 지정되지 않으면 기본적으로 PaimonS3 구현을 사용해요.
가상 컬럼
_path— 파일 경로. 타입:LowCardinality(String)_file— 파일 이름. 타입:LowCardinality(String)_size— 파일 크기(바이트). 타입:Nullable(UInt64). 파일 크기를 알 수 없으면 값은NULL_time— 파일의 마지막 수정 시간. 타입:Nullable(DateTime). 시간을 알 수 없으면 값은NULL_etag— 파일의 etag. 타입:LowCardinality(String). etag를 알 수 없으면 값은NULL
지원되는 데이터 타입
| Paimon Data Type | ClickHouse Data Type |
|---|---|
| BOOLEAN | Int8 |
| TINYINT | Int8 |
| SMALLINT | Int16 |
| INTEGER | Int32 |
| BIGINT | Int64 |
| FLOAT | Float32 |
| DOUBLE | Float64 |
| STRING,VARCHAR,BYTES,VARBINARY | String |
| DATE | Date |
| TIME(p),TIME | Time('UTC') |
| TIMESTAMP(p) WITH LOCAL TIME ZONE | DateTime64 |
| TIMESTAMP(p) | DateTime64('UTC') |
| CHAR | FixedString(1) |
| BINARY(n) | FixedString(n) |
| DECIMAL(P,S) | Decimal(P,S) |
| ARRAY | Array |
| MAP | Map |
지원되는 파티션
Paimon 파티션 키에서 지원되는 데이터 타입:
CHARVARCHARBOOLEANDECIMALTINYINTSMALLINTINTEGERDATETIMETIMESTAMPTIMESTAMP WITH LOCAL TIME ZONEBIGINTFLOATDOUBLE