Apache Iceberg™ 테이블에 데이터 로드하기

Snowflake는 Snowflake가 관리하는 Iceberg 테이블에 데이터를 로딩할 때 다음과 같은 선택 사항을 지원합니다.

파일 형식

표준 Snowflake 테이블에 로드할 수 있도록 지원되는 형식의 파일에서 Iceberg 테이블로 데이터를 로드할 수 있습니다.

CSV, JSON, Avro 및 ORC 의 경우 Snowflake는 비 Parquet 파일 형식의 데이터를 Iceberg Parquet 파일로 변환하여 Iceberg 테이블의 기본 위치에 데이터를 저장합니다. 유형 변환이 필요한 이러한 파일 형식 로딩 시나리오에는 기본 LOAD_MODE = FULL_INGEST 옵션만 지원됩니다.

Apache Parquet 파일의 경우 Snowflake는 데이터를 테이블 열에 직접 로딩하고 다음 LOAD_MODE 옵션 중에서 선택할 수 있습니다.

  • FULL_INGEST: 파일을 스캔하고 Iceberg 테이블의 기본 위치 아래에 Parquet 데이터를 다시 작성합니다.

  • ADD_FILES_COPY: Binary는 Iceberg 카탈로그에 등록되지 않은 Iceberg 호환 Apache Parquet 파일을 Iceberg 테이블의 기본 위치에 복사한 다음, 파일을 Iceberg 테이블에 등록합니다.

자세한 내용은 COPY INTO <테이블> 섹션을 참조하십시오.

예제: Iceberg 호환 Parquet 파일 로드하기

이 예제에서는 Iceberg 테이블을 생성한 다음 외부 스테이지의 Iceberg 호환 Parquet 데이터 파일에서 데이터를 로딩하는 방법을 다룹니다.

데모 목적으로 이 예제에서는 다음 리소스를 사용합니다.

  • iceberg_ingest_vol 이라는 외부 볼륨. 외부 볼륨을 생성하려면 외부 볼륨 구성 섹션을 참조하십시오.

  • my_parquet_stage 라는 외부 스테이지에 Iceberg와 호환되는 Parquet 파일이 있습니다. 외부 스테이지를 생성하려면 CREATE STAGE 섹션을 참조하십시오.

  1. Iceberg 호환 Parquet 데이터(TYPE = PARQUET USE_VECTORIZED_SCANNER = TRUE)를 복사하는 데 필요한 구성을 사용하여 스테이징된 Parquet 파일을 설명하는 파일 형식 오브젝트를 만듭니다.

    CREATE OR REPLACE FILE FORMAT my_parquet_format
      TYPE = PARQUET
      USE_VECTORIZED_SCANNER = TRUE;
    
    Copy
  2. 원본 Parquet 파일 데이터 타입과 호환되는 데이터 타입으로 열을 정의하여 Snowflake 관리형 Iceberg 테이블을 만듭니다.

    CREATE OR REPLACE ICEBERG TABLE customer_iceberg_ingest (
      c_custkey INTEGER,
      c_name STRING,
      c_address STRING,
      c_nationkey INTEGER,
      c_phone STRING,
      c_acctbal INTEGER,
      c_mktsegment STRING,
      c_comment STRING
    )
      CATALOG = 'SNOWFLAKE'
      EXTERNAL_VOLUME = 'iceberg_ingest_vol'
      BASE_LOCATION = 'customer_iceberg_ingest/';
    
    Copy

    참고

    예제 문은 Snowflake 데이터 타입에 매핑되는 Iceberg 데이터 타입을 지정합니다. 자세한 내용은 Apache Iceberg™ 테이블의 데이터 타입 섹션을 참조하십시오.

  3. COPY INTO 문을 사용하여 스테이징된 Parquet 파일(URL 경로 바로 아래에 위치)의 데이터를 Iceberg 테이블로 로드합니다.

    COPY INTO customer_iceberg_ingest
      FROM @my_parquet_stage
      FILE_FORMAT = 'my_parquet_format'
      LOAD_MODE = ADD_FILES_COPY
      PURGE = TRUE
      MATCH_BY_COLUMN_NAME = CASE_SENSITIVE;
    
    Copy

    참고

    이 예제에서는 LOAD_MODE = ADD_FILES_COPY 를 지정하여 Snowflake가 파일을 외부 볼륨 위치에 복사본으로 복사한 다음 파일을 테이블에 등록하도록 지시합니다.

    이 선택 사항은 원본 Parquet 파일을 스캔하여 데이터를 새 Parquet 파일로 다시 작성하지 않으므로 파일 요금을 피할 수 있습니다.

    출력:

    +---------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+
    | file                                                          | status | rows_parsed | rows_loaded | error_limit | errors_seen | first_error | first_error_line | first_error_character | first_error_column_name |
    |---------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------|
    | my_parquet_stage/snow_af9mR2HShTY_AABspxOVwhc_0_1_008.parquet | LOADED |       15000 |       15000 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    | my_parquet_stage/snow_af9mR2HShTY_AABspxOVwhc_0_1_006.parquet | LOADED |       15000 |       15000 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    | my_parquet_stage/snow_af9mR2HShTY_AABspxOVwhc_0_1_005.parquet | LOADED |       15000 |       15000 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    | my_parquet_stage/snow_af9mR2HShTY_AABspxOVwhc_0_1_002.parquet | LOADED |           5 |           5 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    | my_parquet_stage/snow_af9mR2HShTY_AABspxOVwhc_0_1_010.parquet | LOADED |       15000 |       15000 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    +---------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+
    
  4. 테이블을 쿼리합니다.

    SELECT
        c_custkey,
        c_name,
        c_mktsegment
      FROM customer_iceberg_ingest
      LIMIT 10;
    
    Copy

    출력:

    +-----------+--------------------+--------------+
    | C_CUSTKEY | C_NAME             | C_MKTSEGMENT |
    |-----------+--------------------+--------------|
    |     75001 | Customer#000075001 | FURNITURE    |
    |     75002 | Customer#000075002 | FURNITURE    |
    |     75003 | Customer#000075003 | MACHINERY    |
    |     75004 | Customer#000075004 | AUTOMOBILE   |
    |     75005 | Customer#000075005 | FURNITURE    |
    |         1 | Customer#000000001 | BUILDING     |
    |         2 | Customer#000000002 | AUTOMOBILE   |
    |         3 | Customer#000000003 | AUTOMOBILE   |
    |         4 | Customer#000000004 | MACHINERY    |
    |         5 | Customer#000000005 | HOUSEHOLD    |
    +-----------+--------------------+--------------+
    

예시: INFER_SCHEMA 함수를 사용하여 생성한 테이블에 Iceberg 호환 Parquet 파일 로딩하기

이 예제에서는 다음을 수행하는 방법을 다룹니다.

  1. INFER_SCHEMA 함수를 사용하여 Apache Iceberg™ 테이블을 생성합니다.

  2. 외부 스테이지에 있는 Iceberg 호환 Parquet 데이터 파일에서 데이터를 로딩합니다.

데모 목적으로 이 예제에서는 다음 리소스를 사용합니다.

  • iceberg_ingest_vol 이라는 외부 볼륨. 외부 볼륨을 생성하려면 외부 볼륨 구성 섹션을 참조하십시오.

  • my_parquet_stage 라는 외부 스테이지에 Iceberg와 호환되는 Parquet 파일이 있습니다. 외부 스테이지를 생성하려면 CREATE STAGE 섹션을 참조하십시오.

  1. Iceberg 호환 Parquet 데이터(TYPE = PARQUET USE_VECTORIZED_SCANNER = TRUE)를 복사하는 데 필요한 구성을 사용하여 스테이징된 Parquet 파일을 설명하는 파일 형식 오브젝트를 만듭니다.

    CREATE OR REPLACE FILE FORMAT my_parquet_format
      TYPE = PARQUET
      USE_VECTORIZED_SCANNER = TRUE;
    
    Copy
  2. my_parquet_stage 스테이지에서 Parquet 파일에 대한 열 정의를 검색합니다.

    SELECT *
      FROM TABLE(
        INFER_SCHEMA(
          LOCATION=>'@my_parquet_stage/customer_iceberg/files-to-ingest/'
          , FILE_FORMAT=>'my_parquet_format'
          , KIND => 'ICEBERG'
          )
        );
    
    Copy

    출력:

    +-------------+---------+----------+---------------------+------------------------------------------------------+----------+
    | COLUMN_NAME | TYPE    | NULLABLE | EXPRESSION          | FILENAMES                                            | ORDER_ID |
    |-------------+---------+----------+---------------------+------------------------------------------------------|----------+
    | id          | INT     | False    | $1:id::INT          | customer_iceberg/files-to-ingest/customers.parquet   | 0        |
    | custnum     | INT     | False    | $1:custnum::INT     | customer_iceberg/files-to-ingest/customers.parquet   | 1        |
    +-------------+---------+----------+---------------------+------------------------------------------------------+----------+
    
  3. 감지된 스키마를 사용하여 Iceberg 테이블을 생성합니다.

    CREATE ICEBERG TABLE myicebergtable
      USING TEMPLATE (
        SELECT ARRAY_AGG(OBJECT_CONSTRUCT(*))
        WITHIN GROUP (ORDER BY order_id)
          FROM TABLE(
            INFER_SCHEMA(
              LOCATION=>'@my_parquet_stage/customer_iceberg/files-to-ingest/',
              FILE_FORMAT=>'my_parquet_format',
              KIND => 'ICEBERG'
            )
          ))
     ... {rest of the ICEBERG options}
     ;
    
    Copy

    참고

    ARRAY_AGG(OBJECT_CONSTRUCT()) 에 대해 * 를 사용하면 반환된 결과가 16MB 보다 클 경우 오류가 발생할 수 있습니다. 큰 결과 세트에는 * 를 사용하지 말고 쿼리에는 필수 열인 COLUMN NAME, TYPE, NULLABLE 만 사용하는 것이 좋습니다. WITHIN GROUP (ORDER BY order_id) 를 사용할 때 선택적 열 ORDER_ID 를 포함할 수 있습니다.

  4. COPY INTO 문을 사용하여 스테이징된 Parquet 파일의 데이터를 Iceberg 테이블로 로딩합니다.

    COPY INTO myicebergtable
      FROM @my_parquet_stage/customer_iceberg/files-to-ingest/
      FILE_FORMAT = 'my_parquet_format'
      LOAD_MODE = ADD_FILES_COPY
      MATCH_BY_COLUMN_NAME = CASE_SENSITIVE;
    
    Copy

    참고

    이 예제에서는 LOAD_MODE = ADD_FILES_COPY 를 지정하여 Snowflake가 파일을 외부 볼륨 위치에 복사본으로 복사한 다음 파일을 테이블에 등록하도록 지시합니다.

    이 선택 사항은 원본 Parquet 파일을 스캔하여 데이터를 새 Parquet 파일로 다시 작성하지 않으므로 파일 요금을 피할 수 있습니다.

    출력:

    +---------------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+
    | file                                                                | status | rows_parsed | rows_loaded | error_limit | errors_seen | first_error | first_error_line | first_error_character | first_error_column_name |
    |---------------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------|
    | my_parquet_stage/customer_iceberg/files-to-ingest/customers.parquet | LOADED |       15000 |       15000 |           0 |           0 | NULL        |             NULL |                  NULL | NULL                    |
    +---------------------------------------------------------------------+--------+-------------+-------------+-------------+-------------+-------------+------------------+-----------------------+-------------------------+
    
  5. 데이터 로딩 후 테이블을 쿼리합니다.

    SELECT
        id,
        custnum
      FROM myicebergtable
      LIMIT 10;
    
    Copy

    출력:

    +-----------+---------+
    | id        | custnum |
    |-----------+---------+
    |         1 |   75001 |
    |         2 |   75002 |
    |         3 |   75003 |
    |         4 |   75004 |
    |         5 |   75005 |
    |         6 |   75006 |
    |         7 |   75007 |
    |         8 |   75008 |
    |         9 |   75009 |
    |        10 |   75010 |
    +-----------+---------+