TeradataからSnowflakeへのデータマイグレーション

## TeradataからSnowflakeへのデータ移行検証レポート

オンプレミスのDWHとして広く認知されているTeradataから、クラウドネイティブDWHとして注目されているSnowflakeへのデータ移行を検証したので、その内容を共有します。
移行にあたってはさまざまな課題が発生しましたが、本記事ではそれらの課題と回避方法について説明します。

## 1.データの移行方法
今回のケースでは、既存システム（Teradata）および新システム（Snowflake）ともにAWS上に構築されています。ただし、両者は異なるAWSアカウント上に存在し、セキュリティ制約によりデータベース間の直接接続は不可という前提条件がありました。

また、TeradataのQueryGridを利用すればSnowflakeに対するシームレスかつ高性能なデータアクセスが可能になりますが、今回は使用できない環境だったため、ファイル経由でのデータ移行を行う方針としました。

__使用したツール :__
__・Teradata Parallel Transporter（TPT）Export機能__
→  データのファイル出力に使用
　[ダウンロードサイト]: https://downloads.teradata.com/
__・SnowSQLのCOPY INTOコマンド__
→  Snowflakeへのデータロードに使用
　[ダウンロードサイト]: https://www.snowflake.com/en/developers/downloads/snowsql/

#### 課題1：出力ファイルのサイズと移送時間の問題
移行対象のテーブルにはレコードが非常に多く、TPTでファイル出力を行うとローカルディスクの容量を大きく消費してしまうという問題がありました。また、新システムへファイルを移送するのにも時間がかかるため、非効率でした。

#### 対策1：Amazon S3を活用したストレージ＆転送最適化
既存・新システムともにAWS環境である点を活かし、以下のように対策を講じました

__・TPTの出力先をS3に変更__
→ ローカルディスクへの書き込みを回避することで、容量圧迫の問題を解決。

__・クロスアカウントでS3バケットを共有__
→ 新システム（Snowflake）がアクセス可能な外部ステージ用のS3バケットに直接ファイルを出力することで、ファイルの移送工程自体を省略可能に。

#### ✅ 補足 :
S3に対して出力を行う場合、TPTに加えてS3 Access Moduleのインストールが必要です。
[ダウンロードサイト]: https://downloads.teradata.com/

### データ移行の構成
![construction.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/17d9bb69-471d-4eba-9e41-651b02562704.png)


#### 課題2：データ型の非互換性
移行先であるSnowflakeにおいて、Teradataと同一構成のテーブル定義を準備します。
TeradataとSnowflakeではサポートしているデータ型が異なるため、TeradataのDDL（テーブル定義）をそのままSnowflakeに適用することはできません。

#### 対策2：データ型の対応表を活用
Snowflake社が提供している「Teradata to Snowflake Migration Kit」内のデータ型対応表を参考に、データ型を手動で変換しました。
[ダウンロードサイト - Teradata to Snowflake Migration Open Manual]:
https://www.snowflake.com/thank-you-teradata-to-snowflake-migration-kit/
これにより、Snowflake環境に適したテーブル定義を構築することができました。

#### 3. SQLクエリに関する注意点
移行にあたっては、SQLクエリ内でデータ型に応じた変換や整形処理が必要でした。以下に代表的な対応をまとめます。
|#  |データ型  |説明  |
|---|---|---|
|1  |Char型  |固定長のため不要な空白が出力される → OREPLACE や CAST 関数で除去 |
|2  |Varchar型  |値の前に空白が含まれる場合がある → COALESCE 等で補正 |
|3  |Date型 / Timestamp型  |ファイル出力時に TO_CHAR を使用し、文字列化。形式は YYYY-MM-DD へ統一 |
|4  |Clob型 |Teradataでは最大1GB、Snowflakeの VARIANT型 は最大16MB|
|5  |BLOB型  |同上（VARIANT型での取り扱いで16MB制限）|

### 課題3：CLOB型・BLOB型の取り扱い
CLOB/BLOB型のデータはSnowflakeで直接扱えるサイズに制限（最大16MB）があるため、移行時にそのまま格納できないケースが発生します。

### 対策3：ファイル分割や構造変換による対応
以下のような対策を検討しました。
|#  |対策  |
|---|---|
|1  |CLOB/BLOBデータを .dat ファイル等に出力 → S3に保存し、パス情報を文字列型で格納|
|2  |データを16MB以下に分割し、分割単位で格納|

#### 事前確認の重要性：変換可能かどうかの判断基準
CLOB/BLOBをVARCHARに変換して移行できるかを判断するために、以下のポイントを事前に確認しました
__・格納されているデータがテキストであるか？__
__・データ長がVARCHARの上限（32,000文字）以内で収まっているか？__

✅ 上記の条件を満たす場合は、VARCHAR型に変換してファイル出力・移行が可能です。
※私が担当した過去のシステムでは、CLOBに格納されていたデータの多くが10,000文字未満であったため、VARCHARへの変換で十分に対応できました。

#### 補足
Snowflakeへのデータ移行では、データ型の違い・文字列フォーマットの調整・ファイルサイズ制限など、テーブル定義・クエリ処理の両面で慎重な対応が求められます。
特にCLOB/BLOBなどの大容量データについては、移行前のデータ分析と整理が不可欠です。


## 4.ファイル出力設定（TPT）
Teradata Parallel Transporter（TPT）を使用してデータをファイル出力する際には、接続情報、抽出クエリ、出力先などをTPTスクリプトに記述する必要があります。

Teradataの公式サイトを参照すると、TPTは非常に多機能かつ柔軟な設計になっており、さまざまな記述方法が可能です。ただし、その汎用性が高すぎるがゆえに、どのように書けば良いかがわかりにくいという側面もあります。

※Teradata製品全般に言えることですが、柔軟な機能を多く備えている一方で、初心者にとっては「何をどう設定すればよいのか」が分かりづらく、混乱しやすい点があります。

### 課題4：ファイルサイズが大きくなりすぎる
移行対象のテーブルはレコード数が非常に多く、ファイル出力時に1ファイルあたりのサイズが大きくなりすぎるため、通常のテキストエディタでは開くことができませんでした。

### 対策4：ファイル分割と圧縮出力の活用
この課題に対しては、以下のようなTPTのパラメータ設定により対応しました
__1.ファイル分割設定__
TPTの出力パラメータで、1ファイルあたりのサイズ上限を設定できます。
今回は可読性と操作性を考慮し、1ファイルあたり最大600MBに設定しました。これにより、サイズ制限に達すると自動で別ファイルに分割して出力されるようになります。
__2.圧縮（gz）出力__
TPTは拡張子が.gzで指定されているファイル名に対して、自動でGzip圧縮を行う機能があります。
例えば、出力ファイル名をexport_output_001.gzのように設定することで、TPTが自動的にGzip形式で出力してくれます。

✅ この「拡張子指定で圧縮が有効になる」という仕様はやや特殊ですが、非常に便利です。TPT固有の仕様として知っておくと応用が利きます。

### Teradataのパラメータ
実行コマンド：
tbuild -f job_table.txt -v テーブル名.txt -j job_table -e UTF-8

[-f job_table.txt]
ファイル出力用のパラメータを設定ファイル
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/2131cc07-2592-4a31-93e1-f237b9ba1e55.png" width=70%>

__TPT出力時の主なパラメータ一覧と設定ポイント__
|#  |パラメータ  |説明  |
|---|---|---|
|1  |OpenQuoteMark  |値の先頭に付与する引用符。例："（ダブルクォーテーション） |
|2  |CloseQuoteMark  |値の末尾に付与する引用符。例："（ダブルクォーテーション） |
|3  |AccessModuleName|オブジェクトストレージ（S3等）に書き込むためのアクセスモジュール名 <BR> linux : libs3axsmod.so <BR> windows : libs3axsmod.dll  |
|4  |S3ConfigDir|IAMクレデンシャルファイルの格納ディレクトリパスを指定 |
|5  |S3Bucket|出力先となるS3バケット名  |
|6  |S3Prefix|S3バケット配下の保存先ディレクトリ（プレフィックス）名  |
|7  |S3Object  |出力ファイル名。.gz 拡張子を指定すると自動でGzip圧縮される |
|8  |S3MaxObjectSize  |出力ファイルの最大サイズ（バイト単位）。超過時は自動でファイル分割される |
|9  |S3DontSplitRows  |レコード途中での分割を防ぐため、必ず True を設定することが推奨される  |

__QuoteMark（引用符）の設定について__
OpenQuoteMark および CloseQuoteMark には、ダブルクォーテーション（"） を設定しました。
✅ 理由：
出力対象の文字列カラムに改行コード（LF/CR）やカンマなどの区切り文字が含まれている場合、
QuoteMarkを指定しないと、1行の終端を正しく判別できず、ファイル解析時に不整合が発生する恐れがあるためです。

#### 補足
・出力ファイルをGzip圧縮したい場合は、S3Object に拡張子 .gz を明示的に付けるだけで自動で圧縮されます（TPTの仕様による）。
・巨大なファイルサイズとなる場合は S3MaxObjectSize を設定し、かつ S3DontSplitRows を True にして、レコード単位での分割出力を確実に行えるようにすることが重要です。

[-v テーブル名.txt]
Teradata接続アカウントやクエリを記載するファイル
![parameter2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/7fe35ce0-8260-419c-839e-9b973939df4f.png)

__Teradataからのデータ抽出時に使用するTPTパラメータ一覧__
以下は、Teradataからデータを抽出してファイル出力する際に使用した主なTPTパラメータです。
|#  |パラメータ  |説明  |
|---|---|---|
|1  |ExportTdpid  |Teradataへの接続先識別子（ホスト名等） |
|2  |ExportUsername  |Teradataの接続ユーザー名  |
|3  |ExportUserPassword|上記ユーザーのパスワード  |
|4  |FileWriterTextDelimiter|値の区切り文字（デリミタ）  |
|5  |ExportSelectStmt|抽出対象となるSQLクエリ |

__デリミタに「｜（パイプ）」を採用した理由__
✅ 理由：
カンマ（,）やタブ（\t）などの一般的な区切り文字は、抽出対象の文字列値そのものに含まれている可能性が高く、フィールドの区切りと混同される恐れがあります。
そのため、あまり使用されない記号である | をデリミタとして採用することで、データの構造を明確にし、後続の処理や解析での不具合を回避しました。

[ -j job_table ]
job_table.txtファイル上に記載されている**ジョブ名**

DEFINE JOB **job_table** 

# snowflakeへのデータロード

https://qiita.com/NTTD-niwats/items/e78f031391d02775495b