背景
- Snowflake テーブルを Azure SQL Database に連携したい
- Copy Activity でそのままコピーできるはず、と考えた
現実
- 列マッピング非対応、16MB 単一ファイル制限、専用 Staging Storage 必須といった制約に直面
概要
- 直コピーを試すも列マッピング非対応で断念
- Staging Storage 有効化して一度は対処したが、コストとセキュリティで断念
-
CSV 二段階 (Snowflake → CSV / CSV → SQL) へ方針転換
- Copy1: Snowflake → Blob (SINGLE=false, MAX_FILE_SIZE=256MB, GZIP) で 16MB 制限回避
- Copy2: Blob(CSV) → SQL で列マッピングと型変換を実現
詳細
ステージングが必要と言われた理由
- Snowflake Connector の仕様: Copy Activity で列マッピング未サポート → ソース列とシンク列の整列ができない
- Microsoft ドキュメント上の前提: Snowflake からの COPY UNLOAD は Blob を前提とし、単一ファイルだと 16MB 制限
- Private ネットワーク要件: Self-hosted IR で固定 IP が必要。Azure IR + NAT Gateway 案はコストが大きく却下
直コピーでの躓き
- 列マッピング不可: 22 列の並び替え・型変換ができず破綻
- 16MB 単一ファイル制限: SINGLE=true のまま実行し、"単一ファイルのアンロードモードによる最大ファイルサイズ(16777216)を超えました" で失敗
- Staging 必須の運用負荷: 専用 Storage を追加すると SAS 管理・Lifecycle・IP 制限などが増える
- VNet 内 Storage では接続不可: Snowflake からの COPY UNLOAD は Private Endpoint を解決できず、VNet 内閉域ストレージでは 403/接続失敗。結果として「全ネットワーク許可」または Snowflake IP 許可のパブリック公開が前提となり、セキュリティ/運用コストが増大
採用した CSV 二段階アプローチ
- Copy Activity 1: Snowflake → Blob
- 設定: SINGLE=false, MAX_FILE_SIZE=268435456, COMPRESSION=GZIP, nullValue=""
- 効果: 16MB 制限回避、圧縮で転送量削減、空文字を NULL として扱える
- Copy Activity 2: Blob → SQL
- 設定: DelimitedText で列マッピングを定義、nullValue=""、SQL 側で目的型に変換
- 効果: 列マッピングと型変換を実現、既存 Storage をそのまま利用
インフラと権限の整理
- Storage に csv 保存は必要だが、vnet 内でOK
- Data Factory Managed Identity に Storage Blob Data Contributor を IaC で付与
成果
- 運用簡素化: SAS 更新・Lifecycle・別ストレージのネットワーク管理が不要
- セキュリティ: 既存の Private Endpoint 構成を維持し、パブリック公開不要
- 機能的解決: 列マッピング実現、16MB 制限回避、固定 IP 要件も Self-hosted IR
あとがき
直コピーできるでしょって思ってたが、コネクタ仕様で staging storage を挟む必要があり、当初はやっていたが、納得がいかず、もっと楽な方法があると信じて至った現状の解決策(微妙だけど ![]()
snowflake 側の設定で、単一固定IP許可って制限も意外にうざかったのが今回の泣き所だった