Snowflake Iceberg V3のDeletion Vectorで低更新率DELETEがどれくらい速くなるか検証した
TL;DR
10億行テーブルに対する DELETE 1% では、Snowflake-managed Iceberg V3 の DV-based MoR は 6.05 秒、V2 CoW は 11.85 秒でした。約 2 倍の差です。
- 10億行・20カラム・約115GBのテーブルに対して、1%のDELETE を Snowflake-managed Iceberg V3(MoR有効・2026/5/7 GA)と Iceberg V2(
ENABLE_ICEBERG_MERGE_ON_READ=FALSEの CoW) で比較した - Warehouseは X-Large / Gen2、5回のトリム平均で測定
- 結果、V3 MoRが平均 6.05秒、V2 CoWが平均 11.85秒 で、V3 MoRが約2倍高速
- CDC、SCD Type 2、論理削除(soft delete)など、低更新率の頻繁なDML ではV3 MoR採用で特に計算コスト面のメリットが出やすい
- なお V3 は 2026年5月7日に GA(Generally Available)となり、本番ワークロードでの利用が可能
はじめに
2026年5月7日、Snowflake の Apache Iceberg v3 サポートが GA(Generally Available)になりました。V3 で新たに使えるようになった主な機能とそのメリットは以下の通りです。
V3 で使えるようになった機能一覧(クリックで展開)
Deletion Vector(DV)
DELETE / UPDATE 時にデータファイルを丸ごと書き直す代わりに、削除対象行の情報を別ファイルとして保持して Merge-on-Read を実現する仕組みです。
- メリット: 低更新率の DML で書き込み量が激減し、実行時間・クレジット消費の両方を削減。CDC や soft delete のような「少量変更を頻繁に行う」パターンで特に効果大
- 低更新率の変更で、対象データファイルの全面書き換えを避けやすい
Default Values
カラムにデフォルト値を定義できるようになりました。
- メリット: 既存テーブルに新カラムを追加する際、過去データに対して NULL ではなく意味のあるデフォルト値を遡及適用可能。スキーマ進化が容易に
- 例:
ALTER ICEBERG TABLE t ADD COLUMN status STRING DEFAULT 'active'
Row Lineage
行レベルでの変更追跡情報(_row_id, _last_updated_sequence_number)が Iceberg メタデータに記録されます。
- メリット: CDC(Change Data Capture)パイプラインでの行単位の来歴把握が容易に。どのスナップショットで行が挿入・更新されたかを追跡可能
- Streams と組み合わせることで、外部エンジンからの書き込みも含めた正確な変更検出が可能
新データ型
geography, geometry, nanosecond timestamp, variant が Iceberg テーブルで利用可能になりました。
- メリット: 地理空間データやナノ秒精度のイベントログを Iceberg テーブルで直接扱える。従来 STRING にシリアライズしていたデータを型安全に格納可能
本稿ではこの中でも特に Deletion Vector による MoR(Merge-on-Read)の書き込み性能 にフォーカスし、V3 の DV-based MoR と、V2 を CoW に固定した条件 の実測比較から「V3 MoR はどういうワークロードで効くのか」を明らかにします。
MoR と CoW の違い
Snowflake の Apache Iceberg で、UPDATE / DELETE の扱いは Copy-on-Write(CoW)と Merge-on-Read(MoR)の2通りあります。
CoWは変更行を含むデータファイルを丸ごと書き直す方式。MoRは元ファイルを残して「変更情報」を別ファイルに追加する方式です。
Iceberg V3から導入された Deletion Vector (DV) は、削除対象行の情報を小さなベクターファイルとして保持することでこれを実現します。特に 低更新率のDELETE では対象データファイルの全面書き換えを避けやすく、大きく軽くなる可能性があります。
なお UPDATE も同条件で測定しましたが、同一クエリの5回実行で30倍近い揺らぎが観測され、記事化には追実験が必要と判断し、本稿では DELETE に絞って 結果を報告します。
V3 Deletion Vector(DV)の何が効くのか
V3 MoR(DV)は、削除対象行の情報を別ファイルに持つことで、低更新率のDELETEでは対象データファイルの全面書き換えを避けやすい方式です。ただし Snowflake は常に DV を使うわけではありません。Snowflake の正式ドキュメントの Write method heuristics には、ENABLE_ICEBERG_MERGE_ON_READ=TRUE のとき、1ファイルあたりの削除率が概ね 5% 未満で、かつデータファイルが約 1.6MB より大きい場合に deletion vector を使い、それ以外は CoW を使うと書かれています。
CoW(Iceberg V2含む)との対比は次の通り。
| 観点 | CoW | V3 MoR(DV) |
|---|---|---|
| 影響ファイルの扱い | 該当ファイルを丸ごと書き直し | 元ファイルはそのまま、DVだけ追加 |
| 書き出しバイト量 | 対象ファイル全体 | 削除ビットマップだけ(数KB〜数MB) |
| DELETE 1%の場合 | 対象ファイルほぼ全部を書き直し | 1%分のビットだけ追加 |
| 参照時 | そのまま読める | DVを当てて除外する必要あり |
ただし、正式ドキュメント上も V3 にはファイル単位のヒューリスティックがあります。更新率が閾値(約5%)を超えると自動でCoWにフォールバック し、データファイルが約1.6MB以下だと DV は選ばれません。さらに docs 上、partitioned table では deletion vectors の書き込みに制約があります。つまり「低更新率・一定以上のファイルサイズ・非partitioned寄りの条件ほどV3 MoRが効く」と捉えるのが安全です。
検証条件
| 項目 | 値 |
|---|---|
| 行数 | 1,000,000,000(10億) |
| カラム数 | 20(id, k1, k2, cat, val, ts, c6..c20) |
| データサイズ | 約114〜117GB |
| Warehouse | X-Large / Gen2 |
| セッション | USE_CACHED_RESULT=FALSE |
| 比較対象 | Iceberg V3(ENABLE_ICEBERG_MERGE_ON_READ=TRUE)vs Iceberg V2(ENABLE_ICEBERG_MERGE_ON_READ=FALSE = CoW) |
| 測定 | 別クローンで5回ずつ、最大/最小を除いた3回のトリム平均 |
使ったSQL
テーブル定義
-- Iceberg V3(MoR有効)
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.ICEBERG_V3_T (
id NUMBER(18,0), k1 NUMBER(18,0), k2 NUMBER(18,0),
cat STRING, val NUMBER(18,2), ts TIMESTAMP_NTZ,
c6 STRING, c7 STRING, c8 STRING, c9 STRING, c10 STRING,
c11 STRING, c12 STRING, c13 STRING, c14 STRING, c15 STRING,
c16 STRING, c17 STRING, c18 STRING, c19 STRING, c20 STRING
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=3
ENABLE_ICEBERG_MERGE_ON_READ=TRUE
DATA_RETENTION_TIME_IN_DAYS=0;
-- Iceberg V2(CoW)
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.ICEBERG_V2_T (
id NUMBER(18,0), k1 NUMBER(18,0), k2 NUMBER(18,0),
cat STRING, val NUMBER(18,2), ts TIMESTAMP_NTZ,
c6 STRING, c7 STRING, c8 STRING, c9 STRING, c10 STRING,
c11 STRING, c12 STRING, c13 STRING, c14 STRING, c15 STRING,
c16 STRING, c17 STRING, c18 STRING, c19 STRING, c20 STRING
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=2
ENABLE_ICEBERG_MERGE_ON_READ=FALSE
DATA_RETENTION_TIME_IN_DAYS=0;
INSERT INTO A.PUBLIC.ICEBERG_V2_T SELECT * FROM A.PUBLIC.ICEBERG_V3_T;
1B行投入
INSERT INTO A.PUBLIC.ICEBERG_V3_T
SELECT
seq8() AS id,
UNIFORM(1, 1000, RANDOM()) AS k1,
UNIFORM(1, 1000, RANDOM()) AS k2,
'cat_' || MOD(seq8(), 20) AS cat,
ROUND(UNIFORM(1, 10000, RANDOM())/100.0, 2) AS val,
DATEADD(SECOND, UNIFORM(0, 31536000, RANDOM()), '2025-01-01'::TIMESTAMP_NTZ) AS ts,
RANDSTR(10, RANDOM()) AS c6, RANDSTR(10, RANDOM()) AS c7, ...
FROM TABLE(GENERATOR(ROWCOUNT => 1000000000));
計測用クローン(V3×5、V2×5)
-- V3 側
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.V3_D1 CLONE A.PUBLIC.ICEBERG_V3_T;
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.V3_D2 CLONE A.PUBLIC.ICEBERG_V3_T;
-- ... V3_D3 〜 V3_D5
-- V2 側
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.V2_D1 CLONE A.PUBLIC.ICEBERG_V2_T;
CREATE OR REPLACE ICEBERG TABLE A.PUBLIC.V2_D2 CLONE A.PUBLIC.ICEBERG_V2_T;
-- ... V2_D3 〜 V2_D5
計測クエリ
-- DELETE 1%(約10,007,684行)
DELETE FROM <TABLE> WHERE MOD(k2, 100) = 0;
Warehouseは計測前に次で固定。
ALTER WAREHOUSE ICE_BENCH SET
WAREHOUSE_SIZE='XLARGE'
RESOURCE_CONSTRAINT='STANDARD_GEN_2';
ALTER SESSION SET USE_CACHED_RESULT=FALSE;
結果: DELETE 1%
各5回の実測と、最大・最小を除いたトリム平均。
| テーブル | run1 | run2 | run3 | run4 | run5 | トリム平均 | 対V2倍率 |
|---|---|---|---|---|---|---|---|
| V3 MoR | 6.65 | 6.09 | 5.98 | 5.79 | 6.07 | 6.05s | 1.00x |
| V2 CoW | 11.85 | 11.97 | 11.84 | 11.85 | 11.43 | 11.85s | 1.96x |
単位はすべて秒。削除行数は両方とも 10,007,684 行(MOD(k2,100)=0 相当)。
なぜV3 MoRが速いのか
V3 MoRはDeletion Vectorを使い、削除対象行の情報を別ファイルとして持てるため、低更新率ではデータファイルの全面書き換えを避けやすくなります。一方V2 CoWは削除対象行を含むファイルを丸ごと書き直すため、たとえ1%の削除でも対象ファイル全体を再作成するコストが発生します。
コストパフォーマンス試算
X-Large Warehouse は 16 credits/hour(オンデマンド Standard 換算)。
- V3 MoR: 6.05s × (16 / 3600) = 約 0.027 credits
- V2 CoW: 11.85s × (16 / 3600) = 約 0.053 credits
- 差分: 0.026 credits / 1回のDELETEあたり
DELETE頻度別の年間差額(1 credit ≈ $3.00 で試算):
| 頻度 | 年間実行回数 | 差分(credits) | 年間差額 |
|---|---|---|---|
| 毎日 | 365 | 9.5 | 約 $28 |
| 毎時 | 8,760 | 228 | 約 $683 |
| 5分毎 | 105,120 | 2,733 | 約 $8,200 |
加えて、V3 は 全面的なファイル再書き出しを避けやすい分、ストレージ側の書き込みバイト量 も削減しやすくなります。高頻度CDC系ワークロードほど累積効果が大きい のがポイントです。ただし本稿の試算は、まずは比較しやすい warehouse compute の差分 を中心に見ています。クラウドストレージ料金や cloud services を含む総コストは、環境ごとに別途確認が必要です。
効くケース / 効かないケース
効くケースの具体例
ここでは V3 MoR が効く典型的なパターンを、想定スキーマとクエリ例付きで4つ紹介します。いずれも共通して、ファイル単位の更新率が5%を大きく下回る ため V3 の deletion vector が自動フォールバックせずに使われます。
1. SCD Type 2 の終端クローズ(履歴テーブル)
顧客マスタやアカウント属性の変更を時系列で残す、いわゆる Slowly Changing Dimension Type 2 のテーブルです。変更が発生した行について「現在有効レコード」の valid_to を埋めてクローズする処理が日次・時次で走ります。
CREATE ICEBERG TABLE customer_history (
customer_id NUMBER(18,0),
attribute_snapshot VARIANT,
valid_from TIMESTAMP_NTZ,
valid_to TIMESTAMP_NTZ, -- NULL = 現在有効
is_current BOOLEAN
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=3
ENABLE_ICEBERG_MERGE_ON_READ=TRUE;
-- 終端クローズ(変更があった顧客だけ)
UPDATE customer_history
SET valid_to = CURRENT_TIMESTAMP(),
is_current = FALSE
WHERE customer_id IN (SELECT customer_id FROM staging_changes)
AND is_current = TRUE;
想定規模: 総行数 10億行 / 日次の終端化対象は 数十万〜数百万行 / 更新率 0.1%前後。ファイル単位で見てもほぼ間違いなく5%未満に収まります。
2. soft delete の物理削除バッチ
アプリ側で is_deleted=TRUE とマークされたレコードを、一定期間経過後に物理削除する典型的なパターン。GDPRなど規制対応の導入口になることも多いです。
CREATE ICEBERG TABLE orders (
order_id NUMBER(18,0),
user_id NUMBER(18,0),
amount NUMBER(18,2),
status STRING,
is_deleted BOOLEAN DEFAULT FALSE,
updated_at TIMESTAMP_NTZ
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=3
ENABLE_ICEBERG_MERGE_ON_READ=TRUE;
-- 30日以上前に論理削除されたレコードを物理削除
DELETE FROM orders
WHERE is_deleted = TRUE
AND updated_at < DATEADD(DAY, -30, CURRENT_TIMESTAMP());
想定規模: 総行数 5億〜10億 / 日次削除対象は 0.1〜1%。削除対象は時系列的に古いもの寄りですが、updated_at で分散しているため ほぼ全ファイルに対象行が散らばる ケースが多く、CoWなら実質全書き直しになる典型。V3 MoR の効果が非常に出やすいパターンです。
3. GDPR / プライバシー規制による個人情報削除
特定ユーザーからの削除リクエストに応じて、全ファクトテーブルから該当 user_id の行を物理削除するシナリオ。GDPR、CCPA、日本の個人情報保護法など、どの規制でも類似の運用が必要です。
CREATE ICEBERG TABLE user_events (
event_id NUMBER(18,0),
user_id NUMBER(18,0),
event_type STRING,
payload VARIANT,
event_ts TIMESTAMP_NTZ
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=3
ENABLE_ICEBERG_MERGE_ON_READ=TRUE;
-- 削除リクエストに該当する全ユーザーのイベントを削除
DELETE FROM user_events
WHERE user_id IN (
SELECT user_id
FROM gdpr_deletion_requests
WHERE processed = FALSE
);
想定規模: 総イベント数 50億〜100億 / 削除対象ユーザー 数百〜数千 / イベント換算で 0.001〜0.01%。極めて低更新率な上、削除対象は全期間に散らばるため、CoW では事実上全ファイル書き換えになり非常に重い処理です。V3 MoR ならほぼファイル書き換えなしで完了。
4. イベントストリームの重複排除・値更正
Kafka や Openflow などから取り込んだストリーミングデータで、at-least-once 配信による重複や計測ミスによる誤値が混入した場合の事後クレンジング。
CREATE ICEBERG TABLE telemetry_events (
event_id STRING, -- ソース側の一意ID
device_id NUMBER(18,0),
metric STRING,
value NUMBER(18,4),
event_ts TIMESTAMP_NTZ,
ingested_at TIMESTAMP_NTZ
)
CATALOG='SNOWFLAKE'
EXTERNAL_VOLUME='SNOWFLAKE_MANAGED'
ICEBERG_VERSION=3
ENABLE_ICEBERG_MERGE_ON_READ=TRUE;
-- 別処理で検出した重複イベントを削除
DELETE FROM telemetry_events
WHERE event_id IN (
SELECT event_id FROM duplicate_detection_staging
);
想定規模: 1日あたり数十億件取り込み、重複は 0.01〜0.1% 程度。重複は時系列全体にランダムに散らばるため、V3 deletion vector の効果が最大化するパターンです。
効く / 効きにくいの判断
| 条件 | V3 DV-based MoR との相性 |
|---|---|
| 低更新率の DELETE / UPDATE / MERGE | ◎ |
| 1ファイルあたり削除率が概ね 5% 未満 | ◎ |
| データファイルが約1.6MBより大きい | ◎ |
| 高頻度 CDC / dedupe / soft delete | ◎ |
| 更新率が高い | △(CoWにフォールバックしやすい) |
| 小さいファイルが多い | △ |
| partitioned table | △(現行 docs 上、DV 書き込みに制約あり) |
| 外部エンジンが v3 deletion vectors 非対応 | × |
効かないケース / 注意
- 更新率が高い(ファイルごとに約5%超)場合は V3 が自動で CoW にフォールバック
- データファイルが約1.6MB以下のケースが多い 場合も DV は選ばれにくい
- SELECT 側 は DV を評価する分、わずかにオーバーヘッドが増える
- Compaction は引き続き重要。Snowflake-managed Iceberg なら auto compaction が働きますが、外部カタログ(Glue等)ではメンテナンス戦略を別途設計する必要があります
- 外部エンジン互換性や一部制約を考えると、すべての新規 Iceberg テーブルで無条件に V3 を選べるわけではない
運用上の注意点
-
CATALOG='SNOWFLAKE'のテーブルであれば、External Volume の実体が Snowflake-managed Storage でも S3 external volume でも auto compaction が動く - Snowflake-managed Iceberg V2 でも、
2026_03behavior change bundle 以降は positional delete による MoR が使えます。したがって本稿の比較は、V3 全体 vs V2 全体 ではなく、V3 の DV-based MoR vs V2 を CoW に固定した条件 の比較です - Iceberg v3 サポートは 2026年5月7日に GA。本番ワークロードで利用可能。リリースノート
まとめ
- 1B行・X-Large Gen2・DELETE 1% で V3 MoR は V2 CoW の約2倍速(6.05s vs 11.85s)
- V3 Deletion Vector の本質は「低更新率条件で大きなファイル書き換えを避けやすいこと」
- ただし Snowflake はヒューリスティクスで DV と CoW を切り替えるため、常に DV になるわけではない
- CDC・SCD・soft delete 系の高頻度・低更新率ワークロードで、V3 MoR は特に compute 面で大きなコストパフォーマンス改善をもたらしうる
- 一方、更新率が高い・ファイルが小さい・partitioned table・外部エンジン互換性などの条件では、V3 が自動で CoW にフォールバックしたり、DV 自体が使えないことがある
2026年5月7日にGAとなり本番利用が可能になったため、外部エンジン互換性やpartitioned table などの制約を許容できるなら、新規でIcebergテーブルを作る際に V3 + MoR有効 を有力候補として検討する価値がある、というのが今回の結論です。
Discussion