Se rendre au contenu

SNOWFLAKE ICEBERG

External Tables vs Iceberg Tables Managées
30 juillet 2026 par
Mikaël PAULHIOUT
Snowflake Iceberg : External Tables vs tables Iceberg managées

Snowflake Iceberg : External Tables vs tables Iceberg managées

Snowflake parle deux langages pour lire du Iceberg : External Tables (le mode lecture seule historique) et Iceberg Tables managées (le mode natif depuis 2024). Les deux lisent les mêmes fichiers Parquet, mais l'expérience opérationnelle est très différente.

Le point commun : on parle bien de Iceberg

Dans les deux cas, Snowflake s'appuie sur la spec Apache Iceberg : un catalogue qui pointe vers des fichiers Parquet/ORC/Avro, avec un manifeste qui track les partitions. La différence n'est pas dans le format de stockage, elle est dans qui gère le catalogue.

Comparatif visuel External Table vs Iceberg Table managée dans Snowflake — 2026

Option 1 — External Tables (mode lecture seule)

Vous avez déjà un catalogue Iceberg (Glue, Polaris, Nessie, REST catalog) qui tourne ailleurs. Vous voulez que Snowflake le lise, sans dupliquer les données.

SQLiceberg_external_table.sql
-- Catalogue Glue
CREATE EXTERNAL VOLUME glue_catalog_volume
  STORAGE_LOCATIONS = (
    (NAME = 's3_glue' STORAGE_BASE_URL = 's3://mon-bucket/iceberg/')
  );

-- L'External Table lit les manifests et le Glue catalogue
CREATE EXTERNAL TABLE sales_iceberg_ext
  WITH LOCATION = @glue_catalog_volume/sales/
  FILE_FORMAT = (TYPE = PARQUET)
  CATALOG = 'glue_catalog'
  CATALOG_NAMESPACE = 'analytics'
  CATALOG_TABLE_NAME = 'sales_fact';

-- Lecture classique
SELECT COUNT(*), SUM(amount)
FROM sales_iceberg_ext
WHERE order_date >= '2026-01-01';

Ce que ça fait bien :

  • Lecture directe, zéro copie
  • Un seul stockage source, plusieurs moteurs (Snowflake, Spark, Trino) qui lisent en parallèle
  • Aucun vendor lock-in sur le catalogue

Ce que ça ne fait pas :

  • DML non disponible sur une External Table standalone (mode historique lecture seule) — depuis le 17 octobre 2025, le DML est possible via une catalog-linked database qui synchronise Snowflake avec un catalogue REST externe (Glue, Polaris, Unity). Voir release notes 2025-10-17.
  • Pas de Time Travel Snowflake natif (les snapshots Iceberg restent accessibles via les métadonnées Iceberg, mais hors mécanisme AT OFFSET/TIMESTAMP de Snowflake)
  • Pas d'Auto Clustering / OPTIMIZE orchestré par Snowflake — la compaction doit être pilotée côté Spark/Trino
  • Le Snowflake Optimizer ne s'appuie pas sur les stats de manifest Iceberg natives : le pruning dépend uniquement des stats classiques, donc pruning potentiellement moins efficace qu'en Iceberg managé

C'est la bonne option si votre producteur de données est ailleurs (un pipeline Spark qui écrit du Iceberg) et que Snowflake est juste un consommateur.

Option 2 — Iceberg Tables managées (le mode natif)

Snowflake gère le catalogue pour vous. Vous gardez les bénéfices d'Iceberg (fichiers ouverts, interchangeables avec Spark) mais vous gagnez l'expérience Snowflake classique : DML, Time Travel, clustering.

SQLiceberg_managed_table.sql
-- Snowflake crée et maintient le catalogue automatiquement
CREATE ICEBERG TABLE sales_iceberg_mgd (
  order_id     NUMBER,
  order_date   DATE,
  region_id    NUMBER,
  amount       NUMBER(18, 2)
)
  CATALOG = 'snowflake_catalog'
  EXTERNAL_VOLUME = 's3_glue_volume'
  BASE_LOCATION = 'sales/';

-- DML complet, comme une table normale
INSERT INTO sales_iceberg_mgd
VALUES (1001, '2026-06-04', 3, 149.99);

UPDATE sales_iceberg_mgd
SET amount = amount * 0.95
WHERE region_id = 3;

DELETE FROM sales_iceberg_mgd
WHERE order_date < '2025-01-01';

-- Time Travel : 1 jour par défaut, configurable via DATA_RETENTION_TIME_IN_DAYS
-- (jusqu'à 90 jours en Enterprise+)
SELECT *
FROM sales_iceberg_mgd AT (OFFSET => -3600);

Ce que ça fait bien :

  • INSERT / UPDATE / DELETE / MERGE natif
  • Time Travel piloté par DATA_RETENTION_TIME_IN_DAYS (1 jour par défaut, jusqu'à 90 jours en Enterprise+)
  • Automatic clustering et optimization des petits fichiers en background
  • Streams & Tasks : la table Iceberg est une table Snowflake de première classe
  • Les fichiers Parquet restent compatibles Iceberg : Spark peut les lire en parallèle

Ce qu'il faut savoir :

  • Le catalogue est dans le compte Snowflake (pas dans Glue / Polaris)
  • Le coût de stockage est celui du Cloud (S3 / GCS / ADLS), Snowflake facture les crédits de compute
  • Le vendor lock-in est plus fort : si vous quittez Snowflake, le catalogue ne suit pas (mais les fichiers Parquet restent lisibles par tout moteur Iceberg-compatible)

Ce qui a changé entre 2025 et 2026 : Iceberg Tables deviennent adultes

Les Iceberg Tables managées ont reçu en 2025-2026 un ensemble de capacités qui comblent l'écart avec les tables Snowflake classiques. Trois jalons clés à retenir :

  • Octobre 2025 : GA du write support sur les Externals (catalog-linked), GA de TARGET_FILE_SIZE, arrivée de l'Auto Clustering, data compaction et orphan file deletion
  • Mars 2026 : preview du support de la spec Apache Iceberg v3
  • Avril 2026 : GA des Dynamic Iceberg Tables, avec support de PARTITION BY, TARGET_FILE_SIZE et PATH_LAYOUT comme propriétés de table

Si vous hésitiez à migrer, c'est maintenant le moment.

PARTITION BY — le partitionnement natif Iceberg

Les Iceberg Tables managées supportent les expressions de partition Iceberg standards (identity, bucket, truncate, year, month, day, hour) depuis le blog engineering Snowflake de novembre 2025. La GA officielle comme paramètre PARTITION BY de CREATE ICEBERG TABLE est arrivée le 13 avril 2026, dans le cadre des Dynamic Iceberg Tables. Ce n'est plus le comportement "hidden partition" de Snowflake qui masquait la colonne partitionnée.

SQLiceberg_partition_by.sql
CREATE ICEBERG TABLE events (
  event_id    NUMBER,
  event_time  TIMESTAMP_NTZ,
  payload     VARIANT
)
  CATALOG = 'snowflake_catalog'
  EXTERNAL_VOLUME = 's3_glue_volume'
  BASE_LOCATION = 'events/'
  PARTITION BY DATE_TRUNC('DAY', event_time)
  TARGET_FILE_SIZE = 134217728;

L'avantage : Spark et Trino comprennent ce partitionnement sans metadata join — le pruning est plus efficace cross-engine.

TARGET_FILE_SIZE — contrôlez la taille de vos Parquet

GA depuis le 17 octobre 2025 (release notes). Vous pouvez spécifier la taille cible des fichiers Parquet écrits :

ValeurEffet
134217728 (128 MB)Idéal pour analytics
67108864 (64 MB)Bon équilibre pour charges mixtes
536870912 (512 MB)Optimise le throughput en ingestion massive
SQLiceberg_target_file_size.sql
ALTER TABLE sales_iceberg_mgd
  SET TARGET_FILE_SIZE = 134217728;

PATH_LAYOUT — organisation flexible des fichiers

Contrôlez l'organisation des paths dans le storage. Vous pouvez aligner le chemin physique avec votre stratégie de partition pour optimiser le scan. GA depuis le 13 avril 2026 sur les Dynamic Iceberg Tables (release notes).

SQLiceberg_path_layout.sql
CREATE ICEBERG TABLE logs (
  ts    TIMESTAMP_NTZ,
  level VARCHAR,
  msg   VARCHAR
)
  CATALOG = 'snowflake_catalog'
  EXTERNAL_VOLUME = 's3_logs_volume'
  PATH_LAYOUT = 'dt=%Y-%m-%d/level=%L/'
  PARTITION BY (DATE_TRUNC('DAY', ts), level);

Table Optimization — compaction et re-clustering automatiques

L'optimisation des tables Iceberg (data compaction, manifest compaction, orphan file deletion, automatic clustering) est disponible depuis octobre 2025 sur les Iceberg Tables managées. Snowflake l'orchestre en background. Pour la piloter manuellement :

SQLiceberg_optimize.sql
-- Compaction des petits fichiers
ALTER ICEBERG TABLE sales_iceberg_mgd OPTIMIZE;

-- Re-clustering sur une clé spécifique
ALTER ICEBERG TABLE sales_iceberg_mgd REORGANIZE;

Combinez avec un scheduled task pour une maintenance fully-automated :

SQLiceberg_optimize_task.sql
CREATE TASK optimize_iceberg_task
  WAREHOUSE = 'COMPUTE_WH'
  SCHEDULE = 'USING CRON 0 2 * * *'
AS
  ALTER ICEBERG TABLE sales_iceberg_mgd OPTIMIZE;

Dynamic Iceberg Tables — le déclaratif rencontre Iceberg

Les Dynamic Iceberg Tables combinent le meilleur du déclaratif Dynamic Tables avec le stockage Iceberg ouvert. Preview annoncée le 4 mars 2026 (annonce), GA le 13 avril 2026 avec le support de PARTITION BY, TARGET_FILE_SIZE et PATH_LAYOUT (release notes). Le pipeline se définit en SQL, Snowflake gère le refresh incrémental, et les fichiers restent accessibles par Spark.

SQLdynamic_iceberg_table.sql
CREATE DYNAMIC ICEBERG TABLE daily_sales_agg()
  TARGET_LAG = '1 hour'
  WAREHOUSE = 'COMPUTE_WH'
  AS
SELECT
  DATE_TRUNC('DAY', order_date)       AS sale_day,
  region_id,
  COUNT(*)                            AS order_count,
  SUM(amount)                         AS total_amount
FROM sales_iceberg_mgd
GROUP BY 1, 2;
PropriétéDétail
TARGET_LAGRefresh incrémental toutes les heures
StockageFichiers Parquet Iceberg dans le storage
Lecture externeSpark/Trino peuvent lire sans attendre le refresh
OrchestrationPlus de CRON/Tasks — tout est déclaratif

Comment choisir

CritèreExternal TableIceberg Table managée
Producteur de données hors Snowflake✅ Idéal⚠️ Possible mais contre-productif
Besoin de DML depuis Snowflake✅ Depuis oct. 2025 via catalog-linked database✅ Natif depuis 2024
Time Travel Snowflake (AT OFFSET/TIMESTAMP)✅ Configurable (1 à 90 jours)
Streams / Tasks
Auto Clustering Snowflake✅ (depuis oct. 2025)
CoûtStockage cloud seulStockage cloud + crédits compute
Lecture cross-engine (Spark, Trino)✅ (les fichiers sont standards)
Lock-in catalogueAucun (Glue/Polaris)Snowflake uniquement
PARTITION BY Iceberg natif✅ (nov. 2025, GA avr. 2026)
Table Optimization✅ (oct. 2025)
Dynamic Iceberg Tables✅ (GA avr. 2026)
Apache Iceberg v3 specEn preview (mars 2026)En preview (mars 2026)

La règle simple :

  • Vous consommez du Iceberg produit ailleurs → External Table
  • Vous produisez de la donnée dans Snowflake avec une interop future → Iceberg Table managée

Le piège classique

Le plus fréquent : créer une External Table "parce qu'on veut de l'Iceberg" alors qu'on n'a pas de catalogue externe. Dans ce cas, vous perdez tout ce qui fait la valeur d'Iceberg managé (DML, Time Travel, streams, optimisation 2025-2026) sans gagner l'interop qu'apporte l'External Table.

Posez la question : "Qui maintient le catalogue ?"

  • Personne encore → Iceberg Table managée, Snowflake s'en occupe
  • Glue / Polaris / un autre moteur → External Table, ou catalog-linked database si vous voulez le DML depuis Snowflake

Pattern hybride : lire une table managée depuis Spark

C'est ici que les Iceberg Tables managées deviennent intéressantes. Snowflake écrit des fichiers Parquet + manifests Iceberg standards. Spark peut les lire via le snowflake_catalog REST endpoint, sans dupliquer la donnée.

Pythonspark_lecture.py
# spark_lecture.py — exemple côté Spark
spark.read \
    .format("iceberg") \
    .option("catalog", "snowflake") \
    .option("uri", "https://<account>.snowflakecomputing.com/polaris/api/catalog") \
    .option("warehouse", "my_db") \
    .option("token", "<oauth_token>") \
    .load("my_db.public.sales_iceberg_mgd") \
    .filter(col("order_date") >= "2026-01-01") \
    .groupBy("region_id") \
    .agg(sum("amount").alias("total")) \
    .show()

Snowflake reste le système de vérité, Spark devient un moteur d'analyse complémentaire. Sans ETL, sans duplication, sans pipeline à maintenir.

Le verdict

Si vous démarrez un projet Snowflake et que vous voulez bénéficier d'Iceberg : Iceberg Table managée. L'écosystème 2025-2026 (Auto Clustering, data compaction, PARTITION BY Iceberg natif, TARGET_FILE_SIZE, Table Optimization, Dynamic Iceberg Tables, preview v3) comble les derniers manques par rapport aux tables classiques.

L'External Table reste l'outil parfait pour les organisations multi-moteurs où Snowflake n'est qu'un consommateur parmi d'autres. Depuis octobre 2025, couplée à une catalog-linked database, elle supporte aussi le DML — ce qui la rend compétitive avec l'Iceberg managée pour les cas d'usage read-write cross-engine.