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

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

以下の記事ではTeradataからsnowflakeへのデータマイグレーションでしたので、今回はSnowflakeからTeradataへのデータ移行を検証したので、その内容を共有します。

https://qiita.com/NTTD-niwats/items/6c99d3914093a6115075

## 1.データの移行方法
Teradataからsnowflakeへのデータマイグレーションの記事と同様にTeradataおよびSnowflakeをAWS上に構築されています。また、両者は異なるAWSアカウント上に存在し、セキュリティ制約によりデータベース間の直接接続は不可という前提条件がありました。

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

### データ移行の構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/54d036d3-9381-41c0-b91e-d467658c1dde.png)

__データ移行の流れ__
1. ネットワーク接続の確立
Teradataが稼働しているAWSアカウント内のEC2インスタンスから、**Snowflakeの外部ステージに相当するS3（別アカウント）**を参照可能とするためのネットワーク接続を確立します。

2. SnowSQLによるデータ転送
SnowSQL の COPY INTO コマンドを利用して、Teradataから出力された移行用ファイルをS3にアップロードします。
このS3はSnowflakeにとって外部ステージとなり、ロードの入り口になります。

3. Snowflakeへのデータ登録
Teradata Parallel Transporter（TPT） などのツールを用いて、S3上の移行データをSnowflakeにロードします。
データ形式・圧縮・区切り文字などを一致させることで正確なロードが可能となります。


#### 課題1：データ型の非互換性
Snowflakeに移行する際、TeradataとSnowflakeではサポートしているデータ型が異なるため、
Teradata側のDDL（テーブル定義）をそのままSnowflakeに流用することはできません。

この違いにより、移行先であるSnowflakeにおいて正確なスキーマ設計を行うには、データ型の変換ルールに従って調整する必要があります。

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


#### 補足
Teradataへのデータ移行では、データ型の違い・文字列フォーマットの調整・ファイルサイズ制限など、テーブル定義・クエリ処理の両面で慎重な対応が求められます。
__特にTeradataはPrimaryキーを基に分散データ配置されるため__、移行前のデータ分析と整理が不可欠です。


## 2.SnowSQLのCOPY INTOによるデータエクスポート準備（接続情報の設定）
Snowflakeにデータをロードするには、対象となるアカウントやデータベースへの接続情報が必要です。これらは コマンドラインで直接入力するのではなく、外部ファイルとして設定しておくと管理しやすくなります。
ここではその例として、config.cnf というファイルとしています。

以下は、接続情報を定義した設定ファイルのサンプルです：

![Connection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/0eaa517f-da7a-4688-b4c2-15717ae0b37a.png)

### 外部ファイルの構造について
1つの設定ファイル内に、複数の接続情報をセクションごとにまとめて記述することが可能です。
構成は、以下のように「セクション名」「キー名」「値」で成り立っています。

|カテゴリ|パラメータ|説明|
|----|----|----|
|セクション: connections.xxxx|xxxx は任意の文字列|Snowflake接続情報を識別するセクション名<BR>ここではその例として、xxxx はTESTとしています。|
|キー: アカウント名|accountname|接続先のSnowflakeアカウント名|
|キー: ユーザー名|username|Snowflakeに接続するユーザー名|
|キー: パスワード|password|上記ユーザーのパスワード|
|キー: データベース名|dbname|データ抽出先のデータベース名|
|キー: スキーマ名|schemaname|データ抽出先のスキーマ名|
|キー: ウェアハウス名|warehousename|クエリ実行・データ抽出処理で使用するウェアハウス名|



#### ファイル保存について
設定が完了したら、任意のファイル名で保存します。今回はこの設定ファイルを Config という名前で保存しました。
このように外部ファイルを用意することで、接続先の切り替えが容易になり、スクリプトの汎用性と保守性が向上します。


## 3.SnowSQLのCOPY INTOによるデータエクスポート:エクスポート用SQLファイルの作成
Snowflakeへデータをロードするには、COPY INTO コマンドを記述したSQLファイル（資材）を作成します。ここではその例として、Sample_table.sql というファイルとしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/3ab4b0ac-8c44-4b81-aad1-9528d5d214c8.png)

__パラメータ説明__
|#  |パラメータ|子パラメータ  |説明  |
|---|---|---|---|
|1  |FILE_FORMAT  |type|ファイル形式：CSV を指定 |
|2  |FILE_FORMAT  |FIELD_DELIMITER  |値の区切り文字（デリミタ）。例：（パイプライン） |
|3  |FILE_FORMAT  |FIELD_OPTIONALLY_ENCLOSED_BY  |値の前後に付与する引用符。。例："（ダブルクォーテーション） |
|4  |FILE_FORMAT  |COMPRESSION|出力ファイルをGzip圧縮する場合に使用。例：GZIP  |
|5  |FILE_FORMAT  |NULL_IF|指定した文字列が NULL として扱われる設定。例：('', 'NULL')|
|6  |OVERWRITE|-|既存のファイルを上書きするかどうか。TRUE で上書き可能 |
|7  |SINGLE|-|出力ファイルを1つにまとめるかどうか。例：FALSE（複数ファイルに分割） |
|8  |MAX_FILE_SIZE|-|1ファイルの最大サイズを指定。例：600M（バイト単位） |

__クエリ説明__
|#  |値  |説明  |
|--|--|--|
|1 |@ STAGE_NAME|'@' + 外部ステージ名 を指定。SnowflakeがS3等と接続するための定義 |
|2 |TABLE_NAME|出力ファイル名のプレフィックス※1 |
|3 |DATABASENAME|対象となるテーブルのデータベース名 |
|4 |SCHEMANAME|対象テーブルが存在するスキーマ名 |
|5 |TABLE_NAME|エクスポート対象のテーブル名 |

※1　ファイル形式がCSV + GZIP圧縮かつ複数ファイル出力の場合、Snowflakeでは以下のようなファイル名が自動生成されます：

TABLE_NAME_0_0_0.csv.gz
TABLE_NAME_0_1_0.csv.gz

この命名規則により、出力元・ファイルの分割順序が分かりやすく管理されます。

📘 詳細な構文やパラメータ指定については、以下の公式ドキュメントを参照ください：
https://docs.snowflake.com/ja/sql-reference/sql/copy-into-table

## 4.SnowSQL - COPY INTO によるデータロード：実行手順
作成したSQL資材をもとに、SnowSQLからコマンドを実行してSnowflakeからデータ抽出を行います。
SnowSQLがインストールされた環境から、以下のコマンドを実行します。

#### SnowSQL 実行コマンド例と出力結果
snowsql -config "<接続情報設定ファイル名>" -c "<セクション名>" -f "<SQL資材ファイル名>"

snowsql -config "<接続情報設定ファイル名>" -c "<セクション名>" -f "<SQL資材ファイル名>"


|パラメータ|説明|
|----|----|
|-config|接続情報を定義した設定ファイル名を指定（フルパス可） |
|-c（セクション名）|設定ファイル内で使用する接続セクション名（例：connections.test）|
|-f（SQLファイル）|実行対象のSQLスクリプトファイル名（例：Sample_table.sql）|


#### データ抽出結果のファイル構成
今回の例では、SQL資材内で出力ファイル名のプレフィックスとして TEST_DATA_ を指定しました。そのため、Snowflakeからエクスポートされたファイルは以下のように命名され、自動的に連番と圧縮形式が付与されます

実際の出力イメージ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695372/8a2e2954-5c8f-4872-bf9e-86226d6d4f30.png)


## Teradataへのデータロード
今後更新予定