Apache Iceberg™ tables: Support for Apache Iceberg™ v3 (Preview)

This preview introduces support for v3 of the Apache Iceberg™ specification, but with some considerations and limitations. Unless otherwise noted, both Snowflake-managed and externally managed Iceberg tables are supported in this preview.

Supported Iceberg v3 features

This section lists the Iceberg v3 features that are supported in this preview.

Data types

The following v3 data types are supported in the public preview:

  • geography

  • geometry

  • nanosecond

  • variant

For more information, see Iceberg v3 data types.

Default values

See Default values.

Deletion vectors

See Deletion vectors.

Row lineage

See Row lineage.

Configure the default Iceberg version

Iceberg tables inherently have a format version that they conform to. For externally managed Iceberg tables in a standard Snowflake database, Snowflake retrieves this version from the table’s metadata.

For the following Iceberg tables, the table owner must specify which Iceberg version the table should conform to:

The system default Iceberg format version in Snowflake is v2 but you can set it to v3, if needed. To set the Iceberg version to v3, perform one of the following actions:

  • Use the ICEBERG_VERSION_DEFAULT parameter to set the Iceberg version to 3 at the account, database, or schema level. For more information, see ICEBERG_VERSION_DEFAULT.

  • Specify ICEBERG_VERSION = 3 in your CREATE ICEBERG TABLE statement.

    Note

    If you don’t specify an Iceberg version when you create an Iceberg table, the table defaults to the Iceberg version set for the schema, database, or account. The schema takes precedence over the database, and the database takes precedence over the account.

Caution

Before you use other engines to upgrade an Iceberg tables format-version in table properties to v3, ensure that the table isn’t used by engines or applications that don’t yet support v3. Downgrading format versions isn’t supported in the Apache Iceberg specification. Therefore, all readers and writers must support v3. The default version for Iceberg tables in Snowflake is v2, which can be configured to v3 if needed. Using Snowflake to perform in-place version upgrades isn’t supported at this time.

Usage notes

  • To modify the ICEBERG_VERSION_DEFAULT parameter at the account level, you must be an account administrator; that is, you must be a user with the ACCOUNTADMIN role.

  • To modify the ICEBERG_VERSION_DEFAULT parameter at the database or schema level, the role used to perform the operation must have the OWNERSHIP privilege on the respective database or schema.

Examples

Specify that new Iceberg tables in the my_db database should be created using v3:

ALTER DATABASE my_db SET ICEBERG_VERSION_DEFAULT=3;
Copy

Create a new externally managed Iceberg table with v3. The column definitions included with the command indicate that a new table will be created, or an existing table will be replaced, in the remote catalog. The table is successfully created because this is a new table that doesn’t have an existing version.

CREATE OR REPLACE ICEBERG TABLE my_iceberg_v3_table (
    boolean_col boolean,
    int_col int,
    long_col long,
  )
  CATALOG='my_catalog_integration'
  ICEBERG_VERSION=3;
Copy

Create an externally managed Iceberg table with v3 from an existing table with Iceberg metadata. The lack of a column definitions or format version in this example indicates that this table already exists and the column specification and format version will be inferred from Iceberg metadata from the remote catalog. This example uses catalog-vended credentials, so the EXTERNAL_VOLUME parameter is excluded from the CREATE ICEBERG TABLE statement:

CREATE OR REPLACE ICEBERG TABLE my_iceberg_v3_table
  CATALOG = 'my_catalog_integration'
  CATALOG_TABLE_NAME = 'my_table'
  AUTO_REFRESH = TRUE;
Copy

Note

You can’t use the ALTER ICEBERG TABLE command to change the format version for an existing table.

Get the format version for Iceberg tables

  • The following example shows how to get the Iceberg version for a specific table:

    SHOW PARAMETERS LIKE 'ICEBERG_VERSION' IN TABLE my_v3_iceberg_table;
    
    Copy

    Output:

    +-----------------+-------+---------+-------+---------------------------------------------------+--------+
    | key             | value | default | level | description                                       | type   |
    +-----------------+-------+---------+-------+---------------------------------------------------+--------+
    | ICEBERG_VERSION | 3     | 2       | TABLE | Specifies the Iceberg table format version to ... | NUMBER |
    +-----------------+-------+---------+-------+---------------------------------------------------+--------+
    
  • The following example shows how to get the Iceberg version for a specific table by using the GET_DDL function to retrieve the Iceberg table definition:

    SELECT GET_DDL('ICEBERG_TABLE', 'my_v3_iceberg_table');
    
    Copy

    Output:

     CREATE ICEBERG TABLE my_v3_iceberg_table (
      record VARIANT,
      event_timestamp TIMESTAMP_LTZ(6)
    )
      CATALOG = 'SNOWFLAKE'
      EXTERNAL_VOLUME = 'my_external_volume'
      BASE_LOCATION = 'my_iceberg_table'
      ICEBERG_VERSION = 3;
    

Considerations and limitations for Iceberg v3 features

Consider the following information when you use Iceberg v3 features:

Unsupported Snowflake features

The following Snowflake features aren’t supported in this preview for Iceberg v3:

  • Append-only streams on externally managed Iceberg tables

  • dbt Projects on Snowflake

  • Schema inference

  • Snowpipe Streaming classic architecture

  • SnowGov Regions

  • For tables that use an external catalog, you can’t create Iceberg v3 tables with structured type columns, which includes OBJECT, ARRAY, or MAP. For example, you can’t use CREATE ICEBERG TABLE … AS SELECT (CTAS) to create an externally managed Iceberg v3 table with structured type columns.

    You can create Snowflake-managed Iceberg v3 tables with structured type columns.

  • An in-place upgrade of a Snowflake-managed Iceberg table from v2 to v3, which includes cloning a v2 table, and then upgrading the clone to v3

    Important

    If you use Apache Spark to upgrade an externally managed Iceberg table from v2 to v3, you must use a commit that creates a new snapshot, such as DML operations. Otherwise, if the format-version is updated in table properties without a new snapshot, Snowflake’s manual and automated refresh for the table will fail until a new snapshot is created.

    The following example uses Apache Spark to upgrade an externally managed Iceberg table from v2 to v3:

    ALTER TABLE table_name SET TBLPROPERTIES('format-version'='3');
    
    Copy

Note

  • The list of unsupported features isn’t finalized and is subject to change in the future. The list will be updated, as needed, to reflect the latest unsupported features.

  • For considerations and limitations specific to a v3 feature, see the feature topic for a feature.

Supported Snowflake features

Features that aren’t listed in the Unsupported Snowflake features section are supported. Supported features include those in the following list:

Feature

Notes

Auto-fulfillment for listings

Automated refresh

Catalog integrations

Catalog-linked databases

Cloning

Clustering

Snowflake-managed Iceberg v3 only.

Converting externally managed v3 tables to Snowflake-managed

Supported with the following considerations:

  • Iceberg partitioning remains intact when you convert a v3 Iceberg table.

  • Before conversion, Snowflake never deletes any metadata, manifest lists, or manifests from your external storage.

  • During conversion, Snowflake doesn’t rewrite any metadata or Parquet data files.

  • After conversion, Snowflake is the catalog that is fully responsible for the lifecycle management of the table. Snowflake deletes metadata, manifest lists, manifests, and data files, either created before or after conversion from your external storage after they expire and pass the retention window.

COPY INTO <table>

LOAD_MODE = FULL_INGEST or ADD_FILES COPY are supported with the following considerations:

  • To load the row lineage metadata columns in Parquet files (_row_id and _last_updated_sequence_number), you must use the FULL_INGEST option. The other LOAD_MODE methods aren’t supported. However, Parquet files containing row lineage are likely already part of an Iceberg v3 table. Registering Parquet files by using ADD_FILES_COPY isn’t recommended if those files are already part of another Iceberg table. The best practice for converting externally-managed Iceberg tables to Snowflake-managed Iceberg tables without rewriting files is to use the ALTER ICEBERG TABLE … CONVERT TO MANAGED command.

COPY INTO <location>

Supported with the following limitations:

  • VARIANT, GEOMETRY, and GEOGRAPHY are unloaded as JSON-encoded strings.

  • TIMESTAMP_NTZ(9) is unloaded as milliseconds, not nanoseconds.

  • TIMESTAMP_LTZ(9), ARRAY, OBJECT, and MAP must be casted to other data types.

Data Clean Rooms

Data lineage

Data protection policies

The following data protection policies are supported:

  • Masking policies

  • Row access policies

  • Projection policies

  • Aggregation policies

  • Privacy policies

  • Join policies

Data protection policy enforcement from Apache Spark

Data quality monitoring

Dynamic tables

Write a v3 externally managed Iceberg table as the target of a dynamic table.

Horizon Iceberg REST Catalog API

LOB (Large Object)

Materialized Views

Object tagging

Query acceleration

Replication

Search optimization

Secure views

Sensitive Data Classification

Target file size

Single-argument Iceberg partitioning

Partitioned tables can’t also write deletion vectors; only copy-on-write is supported for partitioned tables.

Snowflake Connector for Kafka

Versions 4.0 or newer.

Snowpark

1.33.0 or newer.

Snowpark pandas API method to_iceberg

Only supported for Iceberg v3 when ICEBERG_VERSION_DEFAULT is set on the account, database, or schema. If ICEBERG_VERSION = 3 is set at the table level, Snowpark pandas API method to_iceberg isn’t supported.

Snowpark Connect for Apache Spark

Writing dataframes to existing Iceberg v3 tables by using an append or overwrite method is supported. Creating a new Iceberg v3 table isn’t supported.

Snowpipe

Snowpipe Streaming high-performance architecture

Sharing

Streams

  • Append-only streams and standard streams are supported on Snowflake-managed Iceberg v3 tables.

  • Insert-only streams and standard streams are supported on externally managed Iceberg v3 tables.

    • To have standard streams produce the correct results, the external engine must write to Iceberg v3 tables with respect to the Iceberg v3 specification. Specifically, newly inserted rows should have _row_id=NULL. Rows that are copied during copy-on-write should maintain the _row_id.

    • MAX_DATA_EXTENSION_TIME_IN_DAYS doesn’t work on externally managed Iceberg v3 tables.

  • When DMLs are committed over multi-statement transactions, append-only streams on Iceberg v3 tables have different semantics compared to Iceberg v2 tables:

    • On Iceberg v2, for append-only streams, if a row is added and then deleted in a multi-statement transaction, this row is considered an insertion.

    • On Iceberg v3, for append-only streams, this row isn’t treated as an insertion.

Table optimization

Unsupported Iceberg v3 features

The following features from the Iceberg v3 specification aren’t supported:

  • Nested variant

  • Multi-argument transforms for partitioning and sorting

  • Table encryption keys

  • UNKNOWN data type

Examples: Support for v3 with existing Snowflake features

This section lists examples of the existing Snowflake features that are supported with v3. A feature listing includes an example for a Snowflake-managed table and an externally managed table, when supported.

For the full list of Snowflake features that are supported in this preview for Iceberg v3, see Supported Snowflake features.

Create a v3 Iceberg table

The following example creates a Snowflake-managed Apache Iceberg™ table that conforms to v3 of the Apache Iceberg™ specification:

CREATE ICEBERG TABLE my_v3_iceberg_table (
  record VARIANT,
  event_timestamp TIMESTAMP_LTZ(6)
)
  CATALOG = 'SNOWFLAKE'
  EXTERNAL_VOLUME = 'my_external_volume'
  BASE_LOCATION = 'my_iceberg_table'
  ICEBERG_VERSION = 3;
Copy

The following example creates an Apache Iceberg™ table that uses a remote Iceberg REST catalog and conforms to v3 of the Apache Iceberg™ specification:

Note

You don’t need to specify ICEBERG_VERSION = 3 with the command because the format version is already defined in the external catalog’s metadata, so Snowflake retrieves this version from the metadata.

CREATE ICEBERG TABLE my_v3_iceberg_table
  EXTERNAL_VOLUME = 'my_external_volume'
  CATALOG = 'my_rest_catalog_integration'
  CATALOG_TABLE_NAME = 'my_remote_table'
  AUTO_REFRESH = TRUE;
Copy

The following example creates a writable Iceberg table in a catalog-linked database with column definitions and conforms to v3 of the Apache Iceberg™ specification:

USE DATABASE my_catalog_linked_db;

USE SCHEMA 'my_namespace';

CREATE OR REPLACE ICEBERG TABLE my_iceberg_table (
  first_name string,
  last_name string,
  amount int,
  create_date date
)
  ICEBERG_VERSION = 3;
Copy

Write to a v3 Iceberg table

DML commands INSERT, UPDATE, DELETE, MERGE, TRUNCATE TABLE, and COPY INTO are supported for writing to Snowflake-managed and externally managed Iceberg v3 tables:

The following example inserts a row into an Apache Iceberg™ table that conforms to v3 of the Apache Iceberg™ table specification:

INSERT INTO my_v3_iceberg_table (id, payload) VALUES (1, PARSE_JSON('{"name": "Alice", "age": 30}'));
Copy

The following example loads files into an Apache Iceberg™ table that conforms to v3 of the Apache Iceberg™ table specification:

COPY INTO my_v3_iceberg_table
  FROM @my_json_stage
  FILE_FORMAT = 'my_json_format'
  MATCH_BY_COLUMN_NAME = CASE_SENSITIVE;
Copy

Load data by using Snowpipe

The following example loads data from files for Iceberg v3 tables, for both Snowflake-managed and externally managed tables:

CREATE PIPE mypipe
  AUTO_INGEST = TRUE
  INTEGRATION = 'MYINT'
  AS
  COPY INTO snowpipe_db.public.my_v3_iceberg_table
  FROM @snowpipe_db.public.mystage
  FILE_FORMAT = (TYPE = 'JSON');
Copy

Note

Snowflake supports additional write features for Iceberg v3. For this list, see the considerations and limitations for Iceberg v3 features, and then see the supported Snowflake features list.

Create a v3 dynamic Iceberg table

The following example writes a v3 Snowflake-managed Iceberg table as the output of a dynamic table:

CREATE DYNAMIC ICEBERG TABLE my_dynamic_iceberg_v3_table (
    num_orders NUMBER(10,0),
    order_day
  )
  TARGET_LAG = '20 minutes'
  WAREHOUSE = my_warehouse
  EXTERNAL_VOLUME = 'my_external_volume'
  CATALOG = 'SNOWFLAKE'
  BASE_LOCATION = 'my_dynamic_iceberg_v3_table'
  ICEBERG_VERSION = 3
  AS
    SELECT
        COUNT(DISTINCT order_id)
        DATE_TRUNC('DAY', order_timestamp_ns) AS order_day
      FROM staging_v3_iceberg_table;
Copy

Note

Writing either a v2 or v3 externally managed Iceberg table as the target of a dynamic table isn’t supported. The output of a dynamic Iceberg table can only be Snowflake-managed.

Query a v3 Iceberg table

The following example queries a Snowflake-managed or externally managed Iceberg v3 table:

SELECT * FROM MY_DB.MY_SCHEMA.MY_ICEBERG_V3_TABLE;
Copy