본문으로 건너뛰기
최종 수정: 에

Paimon Catalog

Doris는 다양한 메타데이터 서비스를 통해 Paimon 테이블 메타데이터에 액세스할 수 있으며, Paimon 데이터 읽기와 쓰기를 지원합니다.

Apache Doris와 Apache Paimon 빠른 시작.

적용 시나리오​

시나리오설명
쿼리 가속Doris의 분산 컴퓨팅 엔진으로 Paimon 데이터에 직접 액세스하여 쿼리를 가속합니다.
데이터 통합Paimon 데이터를 읽어 Doris 내부 테이블에 쓰거나, Doris 컴퓨팅 엔진을 사용하여 ZeroETL 작업을 수행합니다.
데이터 쓰기 반영Doris SQL로 Paimon 테이블을 생성하고 수정하며, 데이터를 추가하거나 덮어쓰고, 기본 키 테이블에서 행 수준 변경을 수행합니다.

Catalog 구성​

구문​

CREATE CATALOG [IF NOT EXISTS] catalog_name PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = '<paimon_catalog_type>',
'warehouse' = '<paimon_warehouse>'
{MetaStoreProperties},
{StorageProperties},
{PaimonProperties},
{CommonProperties}
);
  • <paimon_catalog_type>

    Paimon Catalog의 유형으로, 다음을 지원합니다.

    • filesystem: 기본값입니다. 파일 시스템에 저장된 메타데이터에 직접 액세스합니다.

    • hms: Hive Metastore를 메타데이터 서비스로 사용합니다.

    • dlf: Alibaba Cloud DLF를 메타데이터 서비스로 사용합니다.

    • jdbc: JDBC 인터페이스로 관계형 데이터베이스에 연결하여 메타데이터 서비스로 사용합니다(4.1.0 버전부터 지원).

  • <paimon_warehouse>

    Paimon의 웨어하우스 경로입니다. <paimon_catalog_type>이 filesystem인 경우 이 매개변수를 반드시 지정해야 합니다.

    warehouse 경로는 Database 경로의 상위 디렉터리를 가리켜야 합니다. 예를 들어 테이블 경로가 s3://bucket/path/to/db1/table1이면 warehouse는 s3://bucket/path/to/여야 합니다.

  • {MetaStoreProperties}

    MetaStoreProperties에는 Metastore 메타데이터 서비스의 연결 및 인증 정보를 입력합니다. 자세한 내용은 [지원하는 메타데이터 서비스] 섹션을 참조하세요.

  • {StorageProperties}

    StorageProperties에는 스토리지 시스템과 관련된 연결 및 인증 정보를 입력합니다. 자세한 내용은 [지원하는 스토리지 시스템] 섹션을 참조하세요.

  • {PaimonProperties}

    PaimonProperties에는 Paimon 관련 속성을 입력합니다.

    Doris는 Paimon 메타데이터에 액세스할 때 Paimon Java SDK를 일부 사용하므로, 사용자 지정 매개변수를 Paimon Java SDK에 전달해야 할 수 있습니다. 다음 접두사를 사용할 수 있습니다.

    paimon.s3.xxx
    paimon.s3a.xxx
    paimon.fs.xxx

    이러한 매개변수는 자동으로 변환되어 전달됩니다. 다음은 몇 가지 예입니다.

    입력 매개변수Paimon Java SDK용으로 변환된 매개변수
    "paimon.s3.list.version" = "1""fs.s3a.list.version" = "1"
    "paimon.s3.paging.maximum" = "100""fs.s3a.paging.maximum" = "100"
    "paimon.fs.s3.read.ahead.buffer.size" = "1""fs.s3a.read.ahead.buffer.size" = "1"
    "paimon.s3a.replication.factor" = "3""fs.s3a.replication.factor" = "3"

    Paimon 읽기 옵션

    Doris는 범위가 한정된 Paimon 배치 읽기에 다음 옵션을 지원합니다. Catalog 전체의 쿼리 기본값은 paimon.table-option.<option-key>로 설정하고, 특정 테이블 참조의 설정은 table@options('<option-key>'='<value>')로 재정의할 수 있습니다. 이러한 설정은 Doris의 읽기에만 영향을 주며 물리적 Paimon 테이블 메타데이터는 변경하지 않습니다.

    Paimon 옵션Paimon 기본값Doris에서 허용하는 값효과
    read.batch-size10241부터 65536까지의 정수Paimon JNI 리더의 각 배치에서 요청하는 행 수입니다. Doris가 리더를 열 때 명시적으로 구성한 값이 유지됩니다.
    file-reader-async-threshold10 MB1 MB부터 1 GB까지의 메모리 크기Paimon JNI 리더가 비동기 읽기로 전환하는 파일 크기 임계값입니다.
    file-index.read.enabledtrue불리언읽기 중 Paimon 파일 인덱스 프루닝을 활성화합니다.
    source.split.target-size128 MB양의 메모리 크기Paimon이 데이터 파일을 Doris 스캔 분할로 결합할 때 사용하는 목표 크기입니다.
    source.split.open-file-cost4 MB음수가 아닌 메모리 크기Paimon이 파일을 분할로 결합할 때 파일을 여는 데 드는 예상 비용입니다.
    scan.manifest.parallelism사용 가능한 프로세서 수1부터 256까지의 정수요청하는 매니페스트 읽기 병렬도입니다. 실행 시 Doris는 각 계획 분기의 병렬도를 이 값, 256, 해당 FE 또는 BE에서 사용 가능한 프로세서 수 중 가장 작은 값으로 각각 제한합니다.
    scan.plan-sort-partitionfalse불리언Paimon 스캔 계획 중 파티션을 정렬합니다.

    예를 들어 다음 Catalog 설정은 물리적 Paimon 테이블에 저장된 값을 재정의하며, Doris 쿼리의 기본값이 됩니다.

    CREATE CATALOG paimon_hms PROPERTIES (
    "type" = "paimon",
    "paimon.catalog.type" = "hms",
    "hive.metastore.uris" = "thrift://127.0.0.1:9083",
    "warehouse" = "s3://bucket/paimon-warehouse",
    "paimon.table-option.read.batch-size" = "4096",
    "paimon.table-option.file-reader-async-threshold" = "32 MB",
    "paimon.table-option.source.split.target-size" = "64 MB",
    "paimon.table-option.scan.manifest.parallelism" = "1"
    );

    쿼리에서는 Catalog나 Paimon 테이블 메타데이터를 수정하지 않고도 이러한 기본값을 재정의할 수 있습니다.

    SELECT *
    FROM paimon_hms.db_name.table_name@options(
    'read.batch-size' = '8192',
    'source.split.target-size' = '32 MB'
    );

    각 테이블 참조에는 독립적인 옵션 집합이 있습니다. 예를 들어 동일한 테이블의 두 별칭이 한 명령문에서 서로 다른 배치 크기를 사용할 수 있습니다.

    SELECT small.id
    FROM paimon_hms.db_name.table_name@options('read.batch-size' = '1') small
    JOIN paimon_hms.db_name.table_name@options('read.batch-size' = '8192') large
    ON small.id = large.id;

    우선순위는 높은 순서부터 다음과 같습니다.

    relation @options > Doris Catalog property > physical Paimon table option > Paimon default

    Doris는 이 우선순위를 적용한 후 최종 값을 검증합니다. 따라서 유효한 Catalog 또는 관계 값으로 물리적 테이블의 잘못된 값을 대체할 수 있습니다. 최종 값이 여전히 유효하지 않으면 Doris는 해당 계획 또는 리더 단계가 시작되기 전에 쿼리를 거부합니다. 매니페스트 제한은 파티션, 행 수/통계, 대체 분기 및 시스템 테이블의 매니페스트 계획 전에도 적용됩니다.

    표의 처음 다섯 옵션은 메타데이터에 영향을 주지 않으므로 캐시된 최신 파티션 프로젝션을 재사용할 수 있습니다. scan.manifest.parallelism과 scan.plan-sort-partition은 메타데이터 계획에 영향을 주므로, Doris는 해당 관계에 실제로 적용되는 테이블 핸들을 사용하여 계획을 수립합니다. 쿼리별 값은 Paimon의 JVM 전역 executor 크기를 변경하지 않습니다.

    Doris는 알 수 없거나 유효하지 않은 paimon.table-option.* 속성을 CREATE CATALOG 및 ALTER CATALOG 중에 거부합니다. ALTER CATALOG는 변경할 전체 구성을 적용 전에 검증하므로, 변경이 실패하면 이전 Catalog 구성이 계속 적용됩니다. 이전 Doris 버전에서 영구 저장한 Catalog도 불러올 수 있지만, 지원하지 않거나 유효하지 않은 기존 리더 속성은 적용하지 않고 무시합니다. 해당 속성의 저장된 값은 이미지 및 편집 로그 호환성을 위해 유지합니다.

    스냅샷 및 시작 위치 옵션은 관계 컨텍스트 선택자이므로 @options를 사용해야 합니다. 자세한 내용은 Time Travel을 참조하세요. 이러한 옵션은 Catalog 기본값으로 사용할 수 없습니다. 또한 Doris는 Paimon의 Flink 소스 열거자에 속하는 scan.max-splits-per-task, scan.fallback-branch 및 스트리밍, 레이아웃, 쓰기, 컴팩션 옵션도 제외합니다. 버킷, 기본 키, 파티션, 병합 엔진 및 기타 물리적 동작은 Paimon 테이블의 속성으로 구성하세요. Doris의 CREATE TABLE ... PROPERTIES를 통해 구성할 수도 있습니다.

    명령문 일관성

    하나의 명령문 내에서 Doris는 스키마 바인딩, 파티션 불러오기, 행 수/통계 수집, 시스템 테이블 계획 및 데이터 스캔에 동일한 Paimon 스냅샷과 테이블 세대를 사용합니다. @options로 선택한 스냅샷이나 태그는 중첩된 STRUCT, MAP, ARRAY 필드를 포함하여 해당 과거 버전의 스키마를 사용합니다. 준비된 명령문은 실행할 때마다 새로운 명령문 상태를 가져오므로, 실행 사이에 이루어진 커밋은 새 실행의 선택자와 캐시 설정에 따라 표시됩니다.

    운영상의 안전을 위해 Paimon 스캐너의 DEBUG 구성 메시지에는 배치 크기와 프로젝션된 필드 수만 기록합니다. Doris는 자격 증명이 포함될 수 있는 원시 스캐너 매개변수 맵을 출력하지 않습니다. PaimonJniAsyncReaderThreadCount 프로파일 게이지는 스캐너 전체에서 초당 한 번 샘플링하므로, 최대 한 초 전의 값일 수 있습니다. 이 샘플링은 쿼리 실행이나 스케줄링에 영향을 주지 않습니다. 리더와 IOManager의 정리 작업은 서로 독립적이며, 닫기 작업이 일부 실패한 후에도 안전하게 재시도할 수 있습니다.

    Paimon JNI IOManager

    Paimon 기본 키 테이블에서 JNI 병합 읽기는 여러 파일의 데이터를 정렬하고 병합해야 할 수 있습니다. Paimon IOManager를 활성화하면 이 과정에서 중간 데이터를 BE의 로컬 디스크로 스필할 수 있어, 데이터 양이 많은 병합 읽기의 메모리 부담을 줄일 수 있습니다.

    속성필수기본값설명
    paimon.jni.enable_jni_io_manager아니요falseJNI 읽기에 Paimon IOManager를 활성화할지 여부입니다. 다른 IOManager 속성은 이 속성이 true일 때만 적용됩니다.
    paimon.jni.io_manager.tmp_dir아니요<storage_root_path>/paimon_jni_scanner_io_tmpPaimon IOManager가 임시 스필 파일에 사용하는 로컬 디렉터리입니다. 여러 디렉터리는 쉼표나 콜론으로 구분할 수 있습니다. 이 속성을 생략하면 Doris는 각 BE 스토리지 경로 아래에 디렉터리를 하나씩 생성합니다.
    paimon.jni.io_manager.impl_class아니요Paimon 기본 구현사용자 지정 org.apache.paimon.disk.IOManager 구현의 정규화된 클래스 이름입니다. 모든 BE의 Paimon JNI Scanner 클래스 경로에서 이 클래스를 사용할 수 있어야 합니다.

    다음 예제는 IOManager를 활성화하고 Doris가 BE 스토리지 경로에서 임시 디렉터리를 선택하도록 합니다.

    CREATE CATALOG paimon_hms PROPERTIES (
    "type" = "paimon",
    "paimon.catalog.type" = "hms",
    "hive.metastore.uris" = "thrift://127.0.0.1:9083",
    "warehouse" = "s3://bucket/paimon-warehouse",
    "paimon.jni.enable_jni_io_manager" = "true"
    );

    IOManager를 활성화해도 모든 병합 읽기에서 스필이 강제로 수행되지는 않습니다. Paimon은 병합 리더 수가 sort-spill-threshold를 초과할 때만 스필합니다. 이는 Doris의 동적 리더 옵션이 아닙니다. 다른 스필 동작이 필요하면 물리적 Paimon 테이블에서 구성하세요.

    전용 스필 디스크를 사용하려면 모든 BE에 존재하거나 생성할 수 있는 로컬 경로를 구성하세요.

    "paimon.jni.io_manager.tmp_dir" = "/mnt/ssd1/paimon_io:/mnt/ssd2/paimon_io"

    Doris는 JNI 스캐너마다 IOManager를 생성하고 스캐너와 함께 닫습니다. 구성한 디렉터리에 쓰기 권한이 있고 동시 쿼리를 처리할 충분한 용량이 있는지 확인하세요. 사용자 지정 구현 클래스를 구성한 경우, 해당 클래스는 String[]를 받는 public 생성자, String을 받는 public 생성자 또는 인수가 없는 public 생성자를 제공해야 합니다. 클래스를 불러오거나 인스턴스화하지 못하면 쿼리가 실패합니다.

    이러한 속성은 JNI 경로를 사용하는 Paimon 데이터 테이블 읽기에만 영향을 줍니다. 네이티브 읽기에는 영향을 주지 않습니다. paimon.table-option.file-reader-async-threshold 옵션은 독립적입니다. 이 옵션은 비동기 Paimon 파일 읽기의 임계값을 제어하며, IOManager를 활성화하거나 스필 디렉터리를 구성하지 않습니다.

  • {CommonProperties}

    CommonProperties에는 공통 속성을 입력합니다. Catalog 개요의 [공통 속성] 섹션을 참조하세요.

메타데이터 캐시​

Apache Doris는 외부 데이터 소스에 액세스하는 성능을 높이기 위해 Paimon 메타데이터를 캐시합니다. 메타데이터에는 특정 스냅샷의 테이블 스키마, 최신 스냅샷 ID, 파생된 파티션 프로젝션이 포함됩니다.

팁

Doris 4.1.x 이전 버전에서는 주로 FE 구성 항목으로 메타데이터 캐시를 전역 제어합니다. 자세한 내용은 메타데이터 캐시를 참조하세요. Doris 4.1.x부터는 통합된 meta.cache.* 키를 사용하여 Paimon Catalog의 외부 메타데이터 캐시를 구성합니다. 아래 항목은 현재 버전에 대한 설명입니다. Doris 4.1.x 및 4.2.x는 다른 항목 집합을 사용하며, 이 페이지의 4.x 버전에서 설명합니다.

캐시 속성 구성​

각 캐시 항목은 통합 구성 키 형식인 meta.cache.<engine>.<entry>.{enable,ttl-second,capacity,max-weight}를 사용합니다. Paimon의 <engine>은 paimon입니다. meta.cache.paimon.table.ttl-second는 최신 스냅샷 캐시와 테이블 스키마 캐시의 TTL을 제어합니다.

속성예제의미
enabletrue/false이 캐시 항목을 활성화할지 여부입니다.
ttl-second600, 0, -10은 항목을 비활성화합니다(즉시 적용되며, 최신 데이터를 확인하는 데 사용할 수 있음). -1은 만료되지 않음을 의미합니다. 그 밖의 양의 정수는 액세스 시간을 기준으로 한 TTL을 초 단위로 나타냅니다.
capacity10000개수 기준 최대 캐시 항목 수입니다. 0은 항목을 비활성화합니다.
max-weight1GBDoris 4.1.4부터 지원합니다. 항목이 유지하는 메모리의 추정 사용량에 대한 선택적 제한입니다. 양수여야 하며, 0은 거부됩니다. 아래에 표시된 항목에서만 허용됩니다.

적용 조건: enable=true, ttl-second != 0, capacity > 0일 때 항목이 활성화됩니다. FE 전체, Catalog 또는 항목의 메모리 제한이 있으면 추정 메모리 사용량에 따라 캐시 수용 여부도 제어됩니다. 외부 메타데이터 캐시 메모리 관리를 참조하세요.

캐시 모듈​

다음 항목은 자체 구성 키를 가지며 max-weight를 허용합니다.

항목 (<entry>)속성 키 접두사ENTRY_NAME캐시 내용 및 영향기본 활성화 여부 / TTL / 용량
partition_viewmeta.cache.paimon.partition_view.paimon.partition-view테이블 스냅샷에서 파생된 파티션 프로젝션입니다. 영향: 계획 중 반복적인 파티션 스캔을 줄입니다.true / 86400 s / 1000

다음 캐시에는 <entry> 토큰이 없으며, Catalog 및 FE 전체의 메모리 제한만 따릅니다.

ENTRY_NAME캐시 내용TTL / 용량
paimon-schema-at특정 스냅샷의 테이블 스키마만료 없음 / 10000
paimon-latest-snapshot테이블의 최신 스냅샷 IDmeta.cache.paimon.table.ttl-second (86400 s) / 1000

Paimon 테이블의 컬럼 스키마는 공유 default 엔진(meta.cache.default.schema.*)에서 캐시합니다.

기존 매개변수 매핑 및 변환​

기존 속성 키통합 키설명
schema.cache.ttl-secondmeta.cache.default.schema.ttl-second테이블 스키마 캐시의 만료 시간

모범 사례​

  • 최신 데이터에 실시간 액세스: 각 쿼리에서 Paimon 테이블의 최신 스냅샷을 확인하려면 meta.cache.paimon.table.ttl-second를 0으로 설정하세요.
    -- Disable the latest-snapshot cache to detect the latest snapshots of Paimon tables
    ALTER CATALOG paimon_ctl SET PROPERTIES ("meta.cache.paimon.table.ttl-second" = "0");
  • 성능 최적화: Catalog 속성 변경이 성공하면 영향을 받는 메타데이터 캐시를 삭제하고, 다음 액세스 시 새 구성으로 다시 생성합니다. meta.cache.max-weight 또는 schema.cache.ttl-second를 변경하면 해당 Catalog의 모든 캐시가 삭제됩니다. meta.cache.<engine>.<entry>.*를 변경하면 해당 엔진의 캐시가 삭제됩니다. 이미 진행 중인 쿼리에는 영향을 주지 않습니다. FE 전체 또는 Catalog 메모리 제한이 적용되는 경우, 사용량이 집계되지 않는 별도의 메타데이터 캐시가 생기지 않도록 Paimon SDK 자체의 CachingCatalog는 기본적으로 비활성화됩니다. 명시적으로 설정한 paimon.cache-enabled 속성이 우선 적용됩니다.

관측 가능성​

캐시 메트릭은 information_schema.catalog_meta_cache_statistics 시스템 테이블에서 확인할 수 있습니다. ENTRY_NAME에는 위 표에 나열된 이름이 표시되며, default 엔진 행은 공유 테이블 스키마 캐시입니다.

SELECT engine_name, entry_name,
effective_enabled, ttl_second, capacity,
estimated_size, hit_rate, max_weight, estimated_weight
FROM information_schema.catalog_meta_cache_statistics
WHERE catalog_name = 'paimon_ctl'
ORDER BY engine_name, entry_name;

이 시스템 테이블의 문서를 참조하세요: catalog_meta_cache_statistics.

지원하는 Paimon 버전​

현재 의존하는 Paimon 버전은 1.4.2입니다.

지원하는 Paimon 형식​

  • Paimon Deletion Vector 읽기 지원

지원하는 메타데이터 서비스​

참고: Doris 버전에 따라 지원하는 서비스 유형과 매개변수가 조금씩 다릅니다. [예제] 섹션을 참조하세요.

지원하는 스토리지 시스템​

참고: Doris 버전에 따라 지원하는 서비스 유형과 매개변수가 조금씩 다릅니다. [예제] 섹션을 참조하세요.

지원하는 데이터 형식​

컬럼 타입 매핑​

Doris 4.2의 전체 매핑 표, 정밀도 규칙, 지원하지 않는 타입은 Paimon에서 Doris로의 데이터 타입 매핑을 참조하세요.

Doris는 Paimon JNI 스캐너의 두 경로 모두에서 따옴표로 묶인 최상위 컬럼과 중첩된 STRUCT 필드의 이름 표기를 정확히 유지합니다. 쉼표(region,code), 해시 기호(nested#value), 콜론(colon:name), 공백 또는 Unicode 문자가 포함된 이름도 일반적인 SQL 식별자 인용 외에 추가 이스케이프가 필요하지 않습니다. 읽을 때는 컬럼을 대소문자 구분 없이 일치시키므로, 대문자나 대소문자가 혼합된 컬럼 이름(예: UserId)도 정상적으로 쿼리할 수 있습니다.

버전 참고 사항

4.0 계열의 4.0.8 이전 버전에서는 읽을 때 컬럼 이름의 정확한 일치 여부로 컬럼을 찾았으므로, 대소문자가 혼합된 컬럼 이름이 있는 Paimon 및 Iceberg 테이블에서 잘못된 컬럼을 읽거나 쿼리가 실패할 수 있었습니다. 이 문제는 4.0.8에서 수정되었습니다.

4.1.5부터 명시적인 REFRESH TABLE, REFRESH DATABASE, REFRESH CATALOG 명령은 해당 Paimon 메타데이터 캐시도 무효화합니다. 외부에서 스키마를 변경하거나 테이블을 삭제한 후 다시 생성한 경우, 새로 고침 명령으로 메타데이터를 다시 불러오세요. 이미 시작된 쿼리는 선택한 스냅샷을 유지합니다.

예제​

Hive Metastore​

버전 3.1+
CREATE CATALOG test_paimon_on_hms_hdfs_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'hms',
'warehouse' = 'hdfs://127.0.0.1:8320/user/hive/warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320',
'hadoop.username' = 'doris'
);
버전 2.1 & 3.0

Kerberos 인증 없이 HMS에 액세스

CREATE CATALOG paimon_hms_on_hdfs_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'warehouse' = 'hdfs://127.0.0.1:8320/user/paimon/warehouse/paimon-hms-hdfs-warehouse',
'hadoop.username' = 'doris',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320'
);

Kerberos 인증이 활성화된 HMS에 액세스

CREATE CATALOG paimon_hms_on_hdfs_kerberos_hdfs_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'hms',
'warehouse' = 'hdfs://127.0.0.1:8520/paimon-hms-hdfs-warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.kerberos.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);

Aliyun DLF 메타스토어​

버전 3.1+
CREATE CATALOG paimon_dlf_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'dlf',
'warehouse' = 'oss://bucket/p2_regression_case',
'dlf.uid' = '772905',
'dlf.catalog_id' = 'p2_regression_case',
'dlf.region' = 'cn-beijing',
'dlf.endpoint' = 'dlf.cn-beijing.aliyuncs.com',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);
버전 2.1 & 3.0
CREATE CATALOG paimon_dlf_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'dlf',
'warehouse' = 'oss://bucket/paimon-dlf-oss-warehouse',
'dlf.uid' = '7716890',
'dlf.catalog.id' = 'p2_regression_case',
'dlf.region' = 'cn-beijing',
'dlf.endpoint' = 'dlf.cn-beijing.aliyuncs.com',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);

FileSystem 메타스토어​

버전 3.1+

Kerberos 인증 없이 HMS 및 HDFS 서비스에 액세스

CREATE CATALOG ctl_test_paimon_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'filesystem',
'warehouse' = 'hdfs://127.0.0.1:8020/user/doris/paimon1',
'fs.defaultFS' = 'hdfs://127.0.0.1:8020'
);
버전 2.1 & 3.0

Kerberos 인증 없이 HMS 및 HDFS 서비스에 액세스

CREATE CATALOG ctl_test_paimon_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'filesystem',
'warehouse' = 'hdfs://127.0.0.1:8020/user/doris/paimon1',
'fs.defaultFS' = 'hdfs://127.0.0.1:8020'
);

Paimon JDBC Catalog​

참고

이 기능은 실험적 기능이며, 4.1.0 버전부터 지원합니다.

버전 4.1+

PostgreSQL을 메타데이터 저장소로 사용하고 S3 스토리지 사용

CREATE CATALOG paimon_jdbc_postgresql PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'jdbc',
'paimon.jdbc.uri' = 'jdbc:postgresql://127.0.0.1:5432/paimon_db',
'paimon.jdbc.user' = 'paimon_user',
'paimon.jdbc.password' = 'password',
'paimon.jdbc.driver_class' = 'org.postgresql.Driver',
'paimon.jdbc.driver_url' = '<jdbc_driver_jar>',
'warehouse' = 's3://bucket/warehouse',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
's3.endpoint' = 'https://s3.us-east-1.amazonaws.com',
's3.region' = 'us-east-1'
);

쓰기 작업​

Doris는 Paimon 테이블을 생성하고 수정하며 데이터를 쓸 수 있습니다. 성공한 각 쓰기 작업은 Paimon 스냅샷으로 커밋됩니다. 명령문이 실패하면 Doris는 부분 스냅샷을 게시하지 않습니다.

시작하기 전에​

데이터를 쓰기 전에 다음 항목을 확인하세요.

  • 모든 FE 및 BE 노드에서 Paimon 쓰기 지원이 포함된 Doris 빌드를 실행해야 합니다. 이전 BE 노드가 계속 실행 중인 롤링 업그레이드 중에는 Paimon에 데이터를 쓰지 마세요.
  • Catalog 자격 증명에는 메타스토어를 업데이트하고 웨어하우스에서 파일을 생성, 쓰기, 이름 변경, 삭제할 수 있는 권한이 있어야 합니다. 필요한 정확한 권한은 메타스토어와 스토리지 시스템에 따라 다릅니다.
  • 쓰기는 일반 Paimon 데이터 테이블에만 적용됩니다. Paimon 시스템 테이블과 브랜치, 태그, 스냅샷 또는 타임스탬프를 선택하는 테이블 참조는 읽기 전용입니다.

지원하는 SQL​

작업지원 범위 및 참고 사항
데이터베이스 DDLCREATE DATABASE 및 DROP DATABASE
테이블 DDLCREATE TABLE, CREATE TABLE AS SELECT, DROP TABLE
스키마 변경컬럼 추가, 삭제, 이름 변경, 순서 변경 및 수정
데이터 추가INSERT INTO ... VALUES 및 INSERT INTO ... SELECT
데이터 덮어쓰기전체 테이블, 정적 파티션 및 동적 파티션 INSERT OVERWRITE
행 수준 변경아래 제한 사항에 따라 기본 키 테이블에서 DELETE, UPDATE, MERGE INTO 지원

빠른 시작​

다음 예제는 기본 키 테이블을 생성하고 데이터를 씁니다. Paimon 테이블 옵션은 PROPERTIES에 지정하세요. Doris의 DISTRIBUTE BY 절은 추가하지 마세요.

SWITCH paimon_ctl;
CREATE DATABASE IF NOT EXISTS sales;
USE sales;

CREATE TABLE orders (
order_id BIGINT NOT NULL,
customer STRING NULL,
amount DECIMAL(12, 2) NULL,
status STRING NULL
) ENGINE=paimon
PROPERTIES (
'primary-key' = 'order_id',
'bucket' = '2',
'bucket-key' = 'order_id'
);

INSERT INTO orders VALUES
(1, 'Alice', 99.90, 'NEW'),
(2, 'Bob', 35.00, 'NEW');

UPDATE orders
SET status = 'PAID'
WHERE order_id = 1;

DELETE FROM orders
WHERE order_id = 2;

SELECT * FROM orders ORDER BY order_id;

결과:

+----------+----------+--------+--------+
| order_id | customer | amount | status |
+----------+----------+--------+--------+
| 1 | Alice | 99.90 | PAID |
+----------+----------+--------+--------+

Doris를 통해 테이블 스키마를 변경한 후 새 스키마로 계속 데이터를 쓸 수 있습니다.

ALTER TABLE orders ADD COLUMN note STRING NULL;
ALTER TABLE orders RENAME COLUMN note order_note;

데이터 삽입 및 덮어쓰기​

INSERT INTO는 추가 전용 테이블에 행을 추가하거나 기본 키 테이블의 Paimon 옵션에 따라 행을 병합합니다. 소스는 VALUES, Doris 내부 테이블 또는 다른 외부 테이블일 수 있습니다.

INSERT INTO paimon_ctl.sales.orders
SELECT order_id, customer, amount, status
FROM internal.sales.new_orders;

파티션이 없는 테이블에서 INSERT OVERWRITE는 기존의 모든 행을 대체합니다. 따라서 입력이 비어 있으면 빈 테이블이 됩니다.

INSERT OVERWRITE TABLE paimon_ctl.sales.orders
SELECT order_id, customer, amount, status
FROM internal.sales.orders_snapshot;

파티션이 있는 테이블에는 다음 형식 중 하나를 사용하세요.

-- Replace only the specified partition. The SELECT list omits the static partition column.
INSERT OVERWRITE TABLE paimon_ctl.sales.daily_orders
PARTITION (order_date = '2026-10-08')
SELECT order_id, customer, amount, status
FROM internal.sales.daily_orders_stage;

-- Dynamic overwrite replaces the partitions present in the input and keeps other partitions.
INSERT OVERWRITE TABLE paimon_ctl.sales.daily_orders
SELECT order_id, customer, amount, status, order_date
FROM internal.sales.daily_orders_stage;

기본 키 테이블은 merge-engine이 partial-update인 경우에만 키가 아닌 컬럼을 생략한 삽입을 허용합니다. 추가 전용 테이블에서 생략된 컬럼에는 기본값을 사용하며, 허용되는 경우 NULL을 사용합니다.

데이터 삭제, 업데이트 및 병합​

행 수준 변경에는 Paimon 기본 키 테이블이 필요합니다. 기본 deduplicate 병합 엔진을 사용하는 테이블에서 Doris는 다음 작업을 지원합니다.

DELETE FROM paimon_ctl.sales.orders
WHERE order_id = 10;

UPDATE paimon_ctl.sales.orders
SET amount = amount * 0.9,
status = 'DISCOUNTED'
WHERE order_id = 20;

MERGE INTO paimon_ctl.sales.orders t
USING internal.sales.order_changes s
ON t.order_id = s.order_id
WHEN MATCHED AND s.action = 'DELETE' THEN DELETE
WHEN MATCHED THEN UPDATE SET
customer = s.customer,
amount = s.amount,
status = s.status
WHEN NOT MATCHED THEN INSERT (order_id, customer, amount, status)
VALUES (s.order_id, s.customer, s.amount, s.status);

Paimon이 행 변경을 적용하는 방식으로 인해 다음 제한 사항이 있습니다.

  • UPDATE는 기본 키 컬럼이나 sequence.field로 구성한 컬럼을 수정할 수 없습니다.
  • UPDATE는 MERGE의 업데이트 작업을 포함하여 deduplicate 병합 엔진만 지원하며, changelog-producer=input은 지원하지 않습니다.
  • 파티션 컬럼을 업데이트하려면 동적 버킷 테이블(bucket=-1)에 ignore-delete=false가 설정되어 있어야 합니다.
  • DELETE는 MERGE의 삭제 작업을 포함하여 ignore-delete=false가 필요합니다. 기본 deduplicate 병합 엔진은 이를 직접 지원합니다. partial-update 테이블은 partial-update.remove-record-on-delete=true를 설정해야 하며, aggregation 테이블은 aggregation.remove-record-on-delete=true를 설정해야 합니다.
  • rowkind.field가 구성된 테이블은 이러한 행 수준 명령문을 지원하지 않습니다. cross-partition-upsert.index-ttl이 구성된 동적 버킷 테이블도 지원하지 않습니다.
  • MERGE 명령문은 포함된 작업에 따라 해당 UPDATE 및 DELETE 제한 사항을 따릅니다.

예측 가능한 결과를 얻으려면 MERGE의 소스 측에서 일치 키가 고유하도록 유지하세요. Doris는 여러 소스 행이 동일한 대상 행과 일치하면 명령문을 거부합니다.

운영 참고 사항​

  • 기본 키, 파티션, 버킷, 병합 엔진, 파일 형식, 컴팩션 및 기타 물리적 동작은 Paimon 테이블 속성으로 구성하세요. Doris는 Paimon SDK를 통해 이러한 옵션을 검증합니다.
  • Doris는 현재 Paimon 테이블에 대한 범용 ALTER TABLE ... SET TBLPROPERTIES 작업을 제공하지 않습니다. 생성 후 테이블 속성을 변경하려면 다른 Paimon 엔진을 사용한 후 Doris에서 REFRESH TABLE 또는 REFRESH CATALOG를 실행하세요.
  • 각 BE에 쓰기 스필을 위한 충분한 로컬 디스크 공간을 확보하고, 임시 파일과 커밋 작업에 필요한 웨어하우스 권한을 부여하세요. BE 설정인 paimon_jni_writer_memory_pool_limit_bytes는 각 Paimon JNI writer가 사용하는 메모리 풀을 제한하며, 기본값은 512 MB입니다.
  • 쓰기 또는 스키마 변경이 성공하면 새로운 Doris 명령문은 커밋된 Paimon 스냅샷을 불러옵니다. 기존 명령문은 시작할 때 선택한 스냅샷을 계속 사용합니다.

쿼리 작업​

기본 쿼리​

Catalog를 구성하면 다음과 같이 Catalog의 테이블 데이터를 쿼리할 수 있습니다.

-- 1. Switch to catalog, use database, and query
SWITCH paimon_ctl;
USE paimon_db;
SELECT * FROM paimon_tbl LIMIT 10;

-- 2. Use Paimon database directly
USE paimon_ctl.paimon_db;
SELECT * FROM paimon_tbl LIMIT 10;

-- 3. Use fully qualified name to query
SELECT * FROM paimon_ctl.paimon_db.paimon_tbl LIMIT 10;

파일 메타데이터 컬럼​

4.2.0 버전부터 지원합니다.

Doris는 Paimon 데이터 테이블에 두 개의 숨겨진 메타데이터 컬럼을 제공합니다. 이 컬럼을 사용하면 각 쿼리 결과를 생성한 물리적 데이터 파일과 행을 찾을 수 있습니다.

컬럼타입설명
__paimon_file_pathSTRING NOT NULL원시 데이터 파일에 대해 Paimon이 반환한 원본 경로입니다.
__paimon_row_indexBIGINT NOT NULL전체 데이터 파일 내에서 영부터 시작하는 물리적 행 위치입니다.

사전 요구 사항: 앞의 예제에 설명된 대로 Paimon Catalog를 구성하고, id 컬럼이 있으며 Parquet 또는 ORC 파일을 사용하는 Paimon 데이터 테이블을 생성하세요. 다음 쿼리는 paimon_tbl에 id 값이 1과 2인 행이 이미 있다고 가정합니다.

SELECT id, `__paimon_file_path`, `__paimon_row_index`
FROM paimon_ctl.paimon_db.paimon_tbl
ORDER BY `__paimon_file_path`, `__paimon_row_index`;

결과 예제(파일 경로는 테이블 위치에 따라 달라짐):

+----+------------------------------------------+--------------------+
| id | __paimon_file_path | __paimon_row_index |
+----+------------------------------------------+--------------------+
| 1 | s3://bucket/warehouse/db/table/a.parquet | 0 |
| 2 | s3://bucket/warehouse/db/table/a.parquet | 1 |
+----+------------------------------------------+--------------------+

기본적으로 이 컬럼은 SELECT * 또는 DESC에 표시되지 않습니다.

숨겨진 컬럼을 SELECT *와 DESC에 포함하려면 세션에서 show_hidden_columns를 활성화하세요.

SET show_hidden_columns = true;

관련 세션 변수:

변수타입기본값필수효과
show_hidden_columnsBOOLEANfalse아니요SELECT *와 DESC에 숨겨진 컬럼을 포함합니다. 컬럼을 명시적으로 참조하는 경우에는 필요하지 않습니다.
enable_file_scanner_v2BOOLEANtrue아니요쿼리에서 이러한 메타데이터 컬럼을 참조할 때 활성화 상태를 유지해야 합니다.
force_jni_scannerBOOLEANfalse아니요JNI 리더는 이러한 메타데이터 컬럼을 생성할 수 없으므로 비활성화 상태를 유지해야 합니다.

행 위치는 전체 물리적 파일을 기준으로 합니다. 조건자 필터링, 삭제 벡터 처리 및 스캔 분할은 남은 행의 번호를 다시 매기지 않습니다. 따라서 __paimon_file_path와 __paimon_row_index를 조합하면 현재 테이블 스냅샷 내의 물리적 레코드를 찾을 수 있습니다. 데이터 파일 재작성이나 컴팩션으로 두 값이 모두 변경될 수 있으므로, 안정적인 논리적 행 ID로 사용해서는 안 됩니다.

주의

이 컬럼은 쿼리에 참여하는 모든 Paimon 분할을 FileScannerV2 네이티브 Parquet 또는 ORC 리더를 통해 원시 데이터 파일로 읽을 수 있을 때만 사용할 수 있습니다. JNI 스캔 또는 네이티브/JNI 혼합 스캔을 사용하는 경우, enable_file_scanner_v2가 비활성화된 경우, force_jni_scanner가 활성화된 경우, 선택한 데이터 파일에 네이티브 Parquet/ORC 리더를 사용할 수 없는 경우에는 이 컬럼을 참조하는 쿼리가 실패합니다.

__paimon_file_path와 __paimon_row_index는 대소문자를 구분하지 않는 예약된 이름입니다. Paimon 테이블의 물리적 컬럼 이름으로 사용하지 마세요.

배치 증분 쿼리​

3.1.0 버전부터 지원

Flink와 유사하게 Paimon의 배치 증분 쿼리를 지원합니다.

지정한 스냅샷 또는 타임스탬프 구간 내의 증분 데이터 쿼리를 지원합니다. 구간의 시작점은 포함하고 끝점은 제외합니다.

-- between snapshots [0, 5)
SELECT * FROM paimon_table@incr('startSnapshotId'='0', 'endSnapshotId'='5');

-- between snapshots [0, 5) with specified scan mode
SELECT * FROM paimon_table@incr('startSnapshotId'='0', 'endSnapshotId'='5', 'incrementalBetweenScanMode'='diff');

-- read from start timestamp
SELECT * FROM paimon_table@incr('startTimestamp'='1750844949000');

-- read between timestamp
SELECT * FROM paimon_table@incr('startTimestamp'='1750844949000', 'endTimestamp'='1750944949000');

매개변수:

매개변수설명예제
startSnapshotId시작 스냅샷 ID이며, 0보다 커야 합니다. endSnapshotId와 함께 지정해야 합니다.'startSnapshotId'='3'
endSnapshotId종료 스냅샷 ID이며, startSnapshotId보다 커야 합니다. startSnapshotId와 함께 지정해야 합니다.'endSnapshotId'='10'
incrementalBetweenScanMode증분 읽기 모드를 지정합니다. 기본값은 auto이며, delta, changelog, diff를 지원합니다.'incrementalBetweenScanMode'='delta'
startTimestamp시작 스냅샷 타임스탬프이며, 0 이상이어야 합니다. 단위는 밀리초입니다.'startTimestamp'='1750844949000'
endTimestamp종료 스냅샷 타임스탬프이며, startTimestamp보다 커야 합니다. 선택 사항이며, 지정하지 않으면 startTimestamp부터 최신 스냅샷까지 읽습니다. 단위는 밀리초입니다.'endTimestamp'='1750944949000'
참고 사항

startSnapshotId와 endSnapshotId는 Paimon 매개변수 'incremental-between'='3,10'으로 조합됩니다.

startTimestamp와 endTimestamp는 Paimon 매개변수 'incremental-between-timestamp'='1750844949000,1750944949000'으로 조합됩니다.

incrementalBetweenScanMode는 Paimon 매개변수 incremental-between-scan-mode에 대응합니다.

이 매개변수에 대한 자세한 내용은 Paimon 문서를 참조하세요.

Time Travel​

3.1.0 버전부터 지원

Paimon 테이블의 지정된 스냅샷 읽기를 지원합니다.

기본적으로 읽기 요청은 최신 버전의 스냅샷만 읽습니다.

$snapshots 테이블 함수를 통해 지정한 Paimon 테이블의 스냅샷을 쿼리할 수 있습니다.

Doris > SELECT snapshot_id,commit_time FROM paimon_tbl$snapshots;
+-------------+-------------------------+
| snapshot_id | commit_time |
+-------------+-------------------------+
| 1 | 2025-08-17 06:05:52.740 |
| 2 | 2025-08-17 06:05:52.979 |
| 3 | 2025-08-17 06:05:53.240 |
| 4 | 2025-08-17 06:05:53.561 |
+-------------+-------------------------+

FOR TIME AS OF 및 FOR VERSION AS OF 명령문으로 스냅샷 ID 또는 스냅샷 생성 시각을 기준으로 과거 버전의 데이터를 읽을 수 있습니다. 예제:

-- Notice: Before 3.1.1, only support format like YYYY-MM-DD HH:MM:SS.SSS
-- After 3.1.2, support YYYY-MM-DD HH:MM:SS and YYYY-MM-DD
SELECT * FROM paimon_tbl FOR TIME AS OF "2025-08-17 06:05:52.740";
SELECT * FROM paimon_tbl FOR TIME AS OF "2025-08-17 06:05:52";
SELECT * FROM paimon_tbl FOR TIME AS OF "2025-08-17";

-- Notice: The timestamp must be precise down to the millisecond.
SELECT * FROM paimon_tbl FOR TIME AS OF 1755381952740;
-- Use snapshot id
SELECT * FROM paimon_tbl FOR VERSION AS OF 1;

@options를 사용한 Time Travel​

Paimon 전용 선택자를 사용하려면 쿼리 관계에 @options를 지정하세요. Doris는 scan.snapshot-id, scan.tag-name, scan.version, scan.timestamp, scan.timestamp-millis, scan.watermark, scan.file-creation-time-millis, scan.creation-time-millis, scan.mode를 허용합니다. 스냅샷이나 태그를 선택하면 해당 과거 스키마도 선택됩니다. Doris는 과거 데이터에 최신 스키마를 바인딩하지 않습니다.

-- Read snapshot 1 with the schema stored for snapshot 1.
SELECT id, old_name
FROM paimon_tbl@options('scan.snapshot-id' = '1');

-- A retained tag remains readable even after its ordinary snapshot expires.
SELECT id, old_name
FROM paimon_tbl@options('scan.tag-name' = 'tag1');

테이블 참조에는 시작 위치 옵션을 하나만 지정할 수 있습니다. scan.mode는 Paimon이 해당 조합을 호환 가능한 것으로 정의한 경우에만 위치와 함께 사용할 수 있습니다. 예를 들어 scan.mode='from-creation-timestamp'에는 scan.creation-time-millis가 필요합니다. 알 수 없거나 만료된 스냅샷, 브랜치 또는 태그를 지정하면 최신 테이블로 자동 대체하지 않고 명시적으로 실패합니다. @options 구문은 쿼리 관계에서 지원되며 뷰 정의에 저장할 수 있지만, CTE 참조나 SHOW 같은 쿼리가 아닌 명령에는 적용할 수 없습니다.

브랜치 및 태그​

3.1.0 버전부터 지원

지정한 Paimon 테이블의 브랜치 및 태그 읽기를 지원합니다.

$branches 및 $tags 시스템 테이블로 Paimon 테이블의 브랜치와 태그를 확인할 수 있습니다.

Doris > SELECT * FROM paimon_tbl$branches;
+-------------+-------------------------+
| branch_name | create_time |
+-------------+-------------------------+
| b_1 | 2025-08-17 06:34:37.294 |
| b_2 | 2025-08-17 06:34:37.297 |
+-------------+-------------------------+

Doris > SELECT * FROM paimon_tbl$tags;
+----------+-------------+-----------+-------------------------+--------------+-------------+---------------+
| tag_name | snapshot_id | schema_id | commit_time | record_count | create_time | time_retained |
+----------+-------------+-----------+-------------------------+--------------+-------------+---------------+
| t_1 | 1 | 0 | 2025-08-17 06:05:52.740 | 3 | NULL | NULL |
| t_2 | 2 | 0 | 2025-08-17 06:05:52.979 | 6 | NULL | NULL |
| t_3 | 3 | 0 | 2025-08-17 06:05:53.240 | 9 | NULL | NULL |
| t_4 | 4 | 0 | 2025-08-17 06:05:53.561 | 12 | NULL | NULL |
+----------+-------------+-----------+-------------------------+--------------+-------------+---------------+

Spark/Trino 같은 시스템과 호환되도록 다양한 구문 형식을 지원합니다.

-- BRANCH
SELECT * FROM paimon_tbl@branch(branch1);
SELECT * FROM paimon_tbl@branch("name" = "branch1");

-- TAG
SELECT * FROM paimon_tbl@tag(tag1);
SELECT * FROM paimon_tbl@tag("name" = "tag1");
SELECT * FROM paimon_tbl FOR VERSION AS OF 'tag1';

FOR VERSION AS OF 구문에서는 Doris가 매개변수가 타임스탬프인지 자동으로 판단합니다.

시스템 테이블​

3.1.0 버전부터 지원

Doris는 Paimon 시스템 테이블을 쿼리하여 테이블 관련 메타데이터를 가져올 수 있습니다. 시스템 테이블에서 스냅샷 이력, 매니페스트 파일, 데이터 파일, 파티션 및 기타 정보를 확인할 수 있습니다.

Paimon 테이블의 메타데이터에 액세스하려면 테이블 이름 뒤에 $ 기호를 추가하고 그 뒤에 시스템 테이블 이름을 붙이세요.

SELECT * FROM my_table$system_table_name;

audit_log, binlog, manifests, partitions, ro, row_tracking, table_indexes 시스템 테이블은 관계의 @options를 허용합니다. 선택한 스냅샷이나 태그는 시스템 테이블의 행에 적용되며, 소스 컬럼을 노출하는 시스템 테이블에서는 그에 대응하는 과거 소스 테이블 스키마에도 적용됩니다.

SELECT rowkind, id, old_name
FROM paimon_tbl$audit_log@options('scan.tag-name' = 'tag1');

다른 시스템 테이블은 행을 생성하는 모든 단계에서 선택한 스냅샷을 사용한다고 보장할 수 없으므로 @options를 거부합니다. Paimon 시스템 테이블은 scan.file-creation-time-millis도 거부합니다. 이 파일 필터를 알림 없이 무시하면 요청한 범위 밖의 행이 반환될 수 있기 때문입니다.

참고

Doris는 Paimon 전역 시스템 테이블 읽기를 지원하지 않습니다. 이는 Flink에서만 지원합니다.

schemas​

테이블의 현재 및 과거 스키마 정보를 표시합니다. ALTER TABLE, CREATE TABLE AS 또는 CREATE DATABASE AS 명령문으로 테이블 스키마를 수정하면 각 변경 사항이 schemas 테이블에 레코드로 생성됩니다.

SELECT * FROM my_table$schemas;

결과:

+-----------+--------------------------------------------------------------------------------------------------------------------+----------------+--------------+---------+---------+-------------------------+
| schema_id | fields | partition_keys | primary_keys | options | comment | update_time |
+-----------+--------------------------------------------------------------------------------------------------------------------+----------------+--------------+---------+---------+-------------------------+
| 0 | [{"id":0,"name":"k","type":"INT NOT NULL"},{"id":1,"name":"f0","type":"INT"},{"id":2,"name":"f1","type":"STRING"}] | [] | ["k"] | {} | | 2025-03-04 22:48:41.666 |
+-----------+--------------------------------------------------------------------------------------------------------------------+----------------+--------------+---------+---------+-------------------------+

snapshots​

스냅샷 생성 시각, 커밋 사용자, 작업 유형 등 테이블의 모든 유효한 스냅샷 정보를 표시합니다.

SELECT * FROM my_table$snapshots;

결과:

+-------------+-----------+--------------------------------------+---------------------+-------------+-------------------------+------------------------------------------------------+------------------------------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+
| snapshot_id | schema_id | commit_user | commit_identifier | commit_kind | commit_time | base_manifest_list | delta_manifest_list | changelog_manifest_list | total_record_count | delta_record_count | changelog_record_count | watermark |
+-------------+-----------+--------------------------------------+---------------------+-------------+-------------------------+------------------------------------------------------+------------------------------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+
| 1 | 0 | d7ea4996-92c7-469f-b9ff-c76525954f1c | 9223372036854775807 | APPEND | 2025-03-04 22:48:45.575 | manifest-list-dc5490ba-420c-445a-b6f7-6962d394935c-0 | manifest-list-dc5490ba-420c-445a-b6f7-6962d394935c-1 | NULL | 1 | 1 | 0 | -9223372036854775808 |
| 2 | 0 | 34de47f6-31d1-4f06-b378-c85ef4fbca41 | 9223372036854775807 | APPEND | 2025-07-01 23:11:35.406 | manifest-list-dca6aa5b-6fc6-4b4f-ac22-acfa15bbf171-0 | manifest-list-dca6aa5b-6fc6-4b4f-ac22-acfa15bbf171-1 | NULL | 2 | 1 | 0 | -9223372036854775808 |
| 3 | 0 | 89f67183-a1f8-4ee9-b73c-3f7e992b79a7 | 9223372036854775807 | APPEND | 2025-07-01 23:11:45.114 | manifest-list-6d624d1b-c774-4d95-905e-8258a7b89ecb-0 | manifest-list-6d624d1b-c774-4d95-905e-8258a7b89ecb-1 | NULL | 3 | 1 | 0 | -9223372036854775808 |
| 4 | 0 | 31924a7c-1389-490c-adf1-3bb805b33cd7 | 9223372036854775807 | APPEND | 2025-07-01 23:12:42.042 | manifest-list-09097a51-afde-485e-929b-d2cc39eb6eb2-0 | manifest-list-09097a51-afde-485e-929b-d2cc39eb6eb2-1 | NULL | 5 | 2 | 0 | -9223372036854775808 |
| 5 | 0 | 1e90a80b-41cb-4242-b97c-889728f76810 | 9223372036854775807 | APPEND | 2025-07-01 23:14:26.445 | manifest-list-b8471969-9c4d-41cd-b790-64f6efb2d142-0 | manifest-list-b8471969-9c4d-41cd-b790-64f6efb2d142-1 | NULL | 6 | 1 | 0 | -9223372036854775808 |
| 6 | 0 | 1e90a80b-41cb-4242-b97c-889728f76810 | 9223372036854775807 | COMPACT | 2025-07-01 23:14:29.317 | manifest-list-b8471969-9c4d-41cd-b790-64f6efb2d142-2 | manifest-list-b8471969-9c4d-41cd-b790-64f6efb2d142-3 | NULL | 5 | -1 | 0 | -9223372036854775808 |
+-------------+-----------+--------------------------------------+---------------------+-------------+-------------------------+------------------------------------------------------+------------------------------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+

options​

테이블의 현재 구성 옵션을 표시합니다. 테이블에 포함되지 않은 옵션은 기본값으로 설정되어 있습니다.

SELECT * FROM my_table$options;

결과:

+------------------------+--------------------+
| key | value |
+------------------------+--------------------+
| snapshot.time-retained | 5 h |
+------------------------+--------------------+

files​

파일 형식, 레코드 수, 파일 크기 등 현재 스냅샷이 가리키는 모든 데이터 파일의 정보를 표시합니다.

SELECT * FROM my_table$files;

결과:

mysql> SELECT * FROM my_table$files;
+-----------+--------+------------------------------------------------------------------------------------------------------------------------+-------------+-----------+-------+--------------+--------------------+---------+---------+-------------------+---------------------+---------------------+---------------------+---------------------+-------------------------+-------------+
| partition | bucket | file_path | file_format | schema_id | level | record_count | file_size_in_bytes | min_key | max_key | null_value_counts | min_value_stats | max_value_stats | min_sequence_number | max_sequence_number | creation_time | file_source |
+-----------+--------+------------------------------------------------------------------------------------------------------------------------+-------------+-----------+-------+--------------+--------------------+---------+---------+-------------------+---------------------+---------------------+---------------------+---------------------+-------------------------+-------------+
| {} | 0 | s3://paimon-warehouse-dev/test-flink/cookbook.db/my_table/bucket-0/data-b4a49c57-6ef6-4c04-8813-07a4960d987c-0.parquet | parquet | 0 | 5 | 5 | 1321 | [1] | [6] | {f0=0, f1=0, k=0} | {f0=4, f1=111, k=1} | {f0=11, f1=k7, k=6} | 0 | 5 | 2025-07-01 23:14:23.967 | COMPACT |
+-----------+--------+------------------------------------------------------------------------------------------------------------------------+-------------+-----------+-------+--------------+--------------------+---------+---------+-------------------+---------------------+---------------------+---------------------+---------------------+-------------------------+-------------+

tags​

태그 이름과 연결된 스냅샷을 포함하여 테이블의 모든 태그 정보를 표시합니다.

SELECT * FROM my_table$tags;

결과:

+----------+-------------+-----------+-------------------------+--------------+--------------+
| tag_name | snapshot_id | schema_id | commit_time | record_count | branches |
+----------+-------------+-----------+-------------------------+--------------+--------------+
| tag1 | 1 | 0 | 2025-03-04 14:55:29.344 | 3 | [] |
| tag3 | 3 | 0 | 2025-03-04 14:58:24.691 | 7 | [branch-1] |
+----------+-------------+-----------+-------------------------+--------------+--------------+

branches​

테이블의 알려진 모든 브랜치 정보를 표시합니다.

SELECT * FROM my_table$branches;

결과:

+----------------------+-------------------------+
| branch_name | create_time |
+----------------------+-------------------------+
| branch1 | 2025-03-04 20:31:39.084 |
| branch2 | 2025-03-04 21:11:14.373 |
+----------------------+-------------------------+

consumers​

데이터 소비를 추적하는 데 사용하는 테이블의 소비자 정보를 표시합니다.

SELECT * FROM my_table$consumers;

결과:

+-------------+------------------+
| consumer_id | next_snapshot_id |
+-------------+------------------+
| id1 | 1 |
| id2 | 3 |
+-------------+------------------+

manifests​

테이블의 현재 스냅샷에 대한 매니페스트 파일 정보를 표시합니다.

SELECT * FROM my_table$manifests;

결과:

+-------------------------------------------------+-----------+-----------------+-------------------+-----------+---------------------+---------------------+
| file_name | file_size | num_added_files | num_deleted_files | schema_id | min_partition_stats | max_partition_stats |
+-------------------------------------------------+-----------+-----------------+-------------------+-----------+---------------------+---------------------+
| manifest-3df9bb64-5c11-4aef-994e-d8717fedfc70-0 | 1949 | 1 | 0 | 0 | {} | {} |
| manifest-d7eb4ec4-7238-478a-9ae6-91a4ccebd561-0 | 1946 | 1 | 0 | 0 | {} | {} |
| manifest-3b6f4079-c893-4413-aedc-1e8fbcea6db1-0 | 1948 | 1 | 0 | 0 | {} | {} |
| manifest-abe5177f-82da-4e86-9864-40efffb391bd-0 | 1964 | 1 | 0 | 0 | {} | {} |
| manifest-ee89dff3-a523-4655-a4b8-d7c9e471a1d6-0 | 1949 | 1 | 0 | 0 | {} | {} |
| manifest-ee89dff3-a523-4655-a4b8-d7c9e471a1d6-1 | 2232 | 1 | 5 | 0 | {} | {} |
+-------------------------------------------------+-----------+-----------------+-------------------+-----------+---------------------+---------------------+

aggregation_fields​

집계 테이블의 필드 구성에 사용하는 테이블의 집계 필드 정보를 표시합니다.

SELECT * FROM my_table$aggregation_fields;

결과:

+------------+--------------+----------+------------------+---------+
| field_name | field_type | function | function_options | comment |
+------------+--------------+----------+------------------+---------+
| k | INT NOT NULL | [] | [] | NULL |
| f0 | INT | [] | [] | NULL |
| f1 | STRING | [] | [] | NULL |
+------------+--------------+----------+------------------+---------+

partitions​

각 파티션의 총 레코드 수와 총 파일 크기를 포함하여 테이블의 파티션 정보를 표시합니다.

SELECT * FROM my_table$partitions;

결과:

+-----------+--------------+--------------------+------------+-------------------------+
| partition | record_count | file_size_in_bytes | file_count | last_update_time |
+-----------+--------------+--------------------+------------+-------------------------+
| {} | 5 | 1321 | 1 | 2025-07-01 23:14:23.967 |
+-----------+--------------+--------------------+------------+-------------------------+

buckets​

각 버킷의 통계를 포함하여 테이블의 버킷 정보를 표시합니다.

SELECT * FROM my_table$buckets;

결과:

+-----------+--------+--------------+--------------------+------------+-------------------------+
| partition | bucket | record_count | file_size_in_bytes | file_count | last_update_time |
+-----------+--------+--------------+--------------------+------------+-------------------------+
| {} | 0 | 5 | 1321 | 1 | 2025-07-01 23:14:23.967 |
+-----------+--------+--------------+--------------------+------------+-------------------------+

statistics​

행 수, 데이터 크기 및 기타 통계를 포함하여 테이블의 통계 정보를 표시합니다.

SELECT * FROM my_table$statistics;

결과:

+--------------+------------+-----------------------+------------------+----------+
| snapshot_id | schema_id | mergedRecordCount | mergedRecordSize | colstat |
+--------------+------------+-----------------------+------------------+----------+
| 2 | 0 | 2 | 2 | {} |
+--------------+------------+-----------------------+------------------+----------+

table_indexes​

테이블의 인덱스 정보를 표시합니다.

SELECT * FROM my_table$table_indexes;

결과:

+--------------------------------+-------------+--------------------------------+--------------------------------+----------------------+----------------------+--------------------------------+
| partition | bucket | index_type | file_name | file_size | row_count | dv_ranges |
+--------------------------------+-------------+--------------------------------+--------------------------------+----------------------+----------------------+--------------------------------+
| {2025-03-01} | 0 | HASH | index-70abfebf-149e-4796-9f... | 12 | 3 | <NULL> |
| {2025-04-01} | 0 | DELETION_VECTORS | index-633857e7-cdce-47d2-87... | 33 | 1 | [(data-346cb9c8-4032-4d66-a... |
+--------------------------------+-------------+--------------------------------+--------------------------------+----------------------+----------------------+--------------------------------+

시스템 테이블 활용 사례​

시스템 테이블을 통해 다음 작업과 모니터링을 손쉽게 수행할 수 있습니다.

테이블의 최신 스냅샷 정보를 확인하여 현재 상태 파악​

SELECT snapshot_id, commit_time, commit_kind, total_record_count FROM catalog_sales$snapshots ORDER BY snapshot_id DESC;

결과:

+-------------+-------------------------+-------------+--------------------+
| snapshot_id | commit_time | commit_kind | total_record_count |
+-------------+-------------------------+-------------+--------------------+
| 1 | 2025-07-01 21:21:54.179 | APPEND | 14329288 |
+-------------+-------------------------+-------------+--------------------+

스냅샷별 테이블 정보 확인​

SELECT s.snapshot_id, t.schema_id, t.fields FROM store_sales$snapshots s JOIN store_sales$schemas t ON s.schema_id=t.schema_id;

결과:

+-------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| snapshot_id | schema_id | fields |
+-------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 | 0 | [{"id":0,"name":"ss_sold_date_sk","type":"INT"},{"id":1,"name":"ss_item_sk","type":"INT NOT NULL"},{"id":2,"name":"ss_ticket_number","type":"INT NOT NULL"},{"id":3,"name":"ss_sold_time_sk","type":"INT"},{"id":4,"name":"ss_customer_sk","type":"INT"},{"id":5,"name":"ss_cdemo_sk","type":"INT"},{"id":6,"name":"ss_hdemo_sk","type":"INT"},{"id":7,"name":"ss_addr_sk","type":"INT"},{"id":8,"name":"ss_store_sk","type":"INT"},{"id":9,"name":"ss_promo_sk","type":"INT"},{"id":10,"name":"ss_quantity","type":"INT"},{"id":11,"name":"ss_wholesale_cost","type":"DECIMAL(7, 2)"},{"id":12,"name":"ss_list_price","type":"DECIMAL(7, 2)"},{"id":13,"name":"ss_sales_price","type":"DECIMAL(7, 2)"},{"id":14,"name":"ss_ext_discount_amt","type":"DECIMAL(7, 2)"},{"id":15,"name":"ss_ext_sales_price","type":"DECIMAL(7, 2)"},{"id":16,"name":"ss_ext_wholesale_cost","type":"DECIMAL(7, 2)"},{"id":17,"name":"ss_ext_list_price","type":"DECIMAL(7, 2)"},{"id":18,"name":"ss_ext_tax","type":"DECIMAL(7, 2)"},{"id":19,"name":"ss_coupon_amt","type":"DECIMAL(7, 2)"},{"id":20,"name":"ss_net_paid","type":"DECIMAL(7, 2)"},{"id":21,"name":"ss_net_paid_inc_tax","type":"DECIMAL(7, 2)"},{"id":22,"name":"ss_net_profit","type":"DECIMAL(7, 2)"}] |
| 2 | 0 | [{"id":0,"name":"ss_sold_date_sk","type":"INT"},{"id":1,"name":"ss_item_sk","type":"INT NOT NULL"},{"id":2,"name":"ss_ticket_number","type":"INT NOT NULL"},{"id":3,"name":"ss_sold_time_sk","type":"INT"},{"id":4,"name":"ss_customer_sk","type":"INT"},{"id":5,"name":"ss_cdemo_sk","type":"INT"},{"id":6,"name":"ss_hdemo_sk","type":"INT"},{"id":7,"name":"ss_addr_sk","type":"INT"},{"id":8,"name":"ss_store_sk","type":"INT"},{"id":9,"name":"ss_promo_sk","type":"INT"},{"id":10,"name":"ss_quantity","type":"INT"},{"id":11,"name":"ss_wholesale_cost","type":"DECIMAL(7, 2)"},{"id":12,"name":"ss_list_price","type":"DECIMAL(7, 2)"},{"id":13,"name":"ss_sales_price","type":"DECIMAL(7, 2)"},{"id":14,"name":"ss_ext_discount_amt","type":"DECIMAL(7, 2)"},{"id":15,"name":"ss_ext_sales_price","type":"DECIMAL(7, 2)"},{"id":16,"name":"ss_ext_wholesale_cost","type":"DECIMAL(7, 2)"},{"id":17,"name":"ss_ext_list_price","type":"DECIMAL(7, 2)"},{"id":18,"name":"ss_ext_tax","type":"DECIMAL(7, 2)"},{"id":19,"name":"ss_coupon_amt","type":"DECIMAL(7, 2)"},{"id":20,"name":"ss_net_paid","type":"DECIMAL(7, 2)"},{"id":21,"name":"ss_net_paid_inc_tax","type":"DECIMAL(7, 2)"},{"id":22,"name":"ss_net_profit","type":"DECIMAL(7, 2)"}] |
+-------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

버킷의 데이터 분포 확인​

SELECT `bucket`, COUNT(*) as file_count, SUM(file_size_in_bytes)/1024/1024 as total_size_mb FROM paimon_s3.tpcds.catalog_sales$files GROUP BY `bucket` ORDER BY total_size_mb;
참고

Paimon 시스템 테이블의 많은 필드가 Doris의 키워드이므로 백틱으로 묶어야 합니다.

결과:

+--------+------------+--------------------+
| bucket | file_count | total_size_mb |
+--------+------------+--------------------+
| 35 | 1 | 12.144722938537598 |
| 81 | 1 | 12.143454551696777 |
| 37 | 1 | 12.14071273803711 |
| 36 | 1 | 12.139023780822754 |
| 63 | 1 | 12.137332916259766 |
| 7 | 1 | 12.122495651245117 |
| 15 | 1 | 12.117934226989746 |
| 11 | 1 | 12.116133689880371 |
| 12 | 1 | 12.11155891418457 |
| 46 | 1 | 12.111005783081055 |
+--------+------------+--------------------+

부록​

자주 묻는 질문​

1. Could not find a file io implementation for scheme 's3a' in the classpath

3.1 이전 버전에서 HMS를 메타데이터 저장소로 사용하고 스토리지 측에서 's3a' 또는 's3' 프로토콜을 사용하면 다음 오류가 발생합니다.

java.io.UncheckedIOException: org.apache.paimon.fs.UnsupportedSchemeException: Could not find a file io implementation for scheme 's3a' in the classpath. Hadoop FileSystem also cannot access this path 's3a://`.

3.1 이전 버전

3.1 이전 버전은 s3a 프로토콜을 지원하지 않습니다. 반드시 사용해야 한다면 임시 해결책으로 s3a 관련 매개변수를 추가할 수 있습니다.

3.1 이상 버전

3.1 버전부터는 s3a 매개변수를 명시적으로 추가할 필요가 없습니다. Paimon 스토리지 매개변수를 재정의해야 한다면 paimon.fs. 접두사가 붙은 매개변수를 추가할 수 있습니다. Paimon은 내부적으로 HDFS API를 사용하므로 모든 fs.s3a.* 매개변수를 지원합니다.

예제:

CREATE CATALOG `paimon_hms_on_s3a` PROPERTIES (
"type" = "paimon",
"paimon.catalog.type" = "hms",
"hive.metastore.uris" = "thrift://172.20.48.119:9383",
"warehouse" = "s3a://bucket/paimon_warehouse",
"s3.access_key" = "<ak>",
"s3.secret_key" = "<sk>",
"s3.region" = "ap-east-1",
"s3.endpoint" = "https://s3.ap-east-1.amazonaws.com",
-- Explicitly add s3a parameters
"fs.s3a.access.key" = "<ak>",
"fs.s3a.secret.key" = "<sk>",
"fs.s3a.endpoint.region" = "ap-east-1",
"fs.s3a.endpoint" = "https://s3.ap-east-1.amazonaws.com",
"fs.s3a.impl" = "org.apache.hadoop.fs.s3a.S3AFileSystem"
);

s3 프로토콜을 사용할 때는 Paimon S3 관련 매개변수를 명시적으로 추가해야 합니다. 즉, paimon. 접두사를 추가합니다. 예제:

CREATE CATALOG test_paimon_on_hms_aws_catalog PROPERTIES (
'type' = 'paimon',
'paimon.catalog.type' = 'hms',
'warehouse' = 's3://bucket-hk/paimon_warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
's3.region' = 'ap-east-1',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
-- Explicitly add Paimon S3 parameters
'paimon.s3.region' = 'ap-east-1',
'paimon.s3.endpoint' = 'ap-east-1',
'paimon.s3.access-key' = '<ak>',
'paimon.s3.secret-key' = '<sk>'
);