🔧

Cloud Spanner へ CSV ファイルをインポートする方法

michity2022/11/01に公開

tl;dr

Cloud Spanner に小さい CSV ファイルを手早くインポートするツールとして
Harbourbridge
が利用できます。

はじめに

Cloud Spanner に CSV をインポートする方法として、マニュアルにDataflow を使った方法
が紹介されています。しかし、Dataflow 自体のスピンアップにある程度の時間がかかるため、開発環境はワンタイムで小規模な CSV ファイルをインポートするにはやや大げさである場合があります。
そのような場合に、Go で書かれた Harbourbridge というツールを使うと便利です。

Harbourbridge とは

Harbourbridge とは各種データベースからの移行についての評価とデータの移行を行うツールです。
対応データベースは 2022年10月時点で以下の通りです。

  • PostgreSQL
  • MySQL
  • SQL Server
  • Oracle
  • DynamoDB

これに加えてデータベースではありませんが、CSV からテーブルへのインポートも対応しています。今回はこのインポート機能を使って CSV を Cloud Spanner にインポートしてみます。

Harbourbridge は 100GiB より小さいデータベースの移行を想定しているツールです。これより大きいデータベースであれば、レプリケーションなどを使った方法により移行時のダウンタイムを短くすることができるツールを検討することをお勧めします。

準備

Harbourbridge はテーブル定義の移行とデータ自体の移行の両方をサポートしていますが、CSV はテーブル定義に当たるものがないため予め移行先のテーブルを定義する必要があります。
今回は以下のようなテーブルを予め作成しておきました。

CREATE TABLE `item` (
        `id` INT64 NOT NULL,
        `name` STRING(10),
        `description` STRING(30),
        `price` INT64,
        `created_at` TIMESTAMP,
) PRIMARY KEY (`id`);

データのサンプルは以下の通りです

1,aaaa,bbbbbb,1000,2022-10-27 07:46:56
2,aaaa,bbbbbb,1000,2022-10-27 07:48:32
3,aaaa,bbbbbb,1000,2022-10-27 07:48:34
4,aaaa,bbbbbb,1000,2022-10-27 07:48:34
6,aaaa,bbbbbb,1000,2022-10-27 07:48:35

その他、Cloud Spanner 自体へのアクセス、GCS からファイルをダウンロードする場合にはその権限などを準備ください。

実行

CSV ファイルのインポートには大きく分けて2種類あって、マニフェストファイルというテーブルと CSV ファイルの対応関係を記述する場合と、指定しない場合です。
マニフェストファイルを与えたときの実行例です。

harbourbridge data -source=csv \
-source-profile="manifest=マニフェストファイル,nullStr=NULL" \
-target-profile="dbName=DB名,instance=インスタンス名" 

マニフェストファイルとは、インポート先のテーブルと CSV ファイルの対応関係を JSON で記述したものです。
マニフェストファイル のサンプルは以下の通り。

[
    {
      "table_name": "item",
      "file_patterns": [
              "gs://バケット名/item.csv"
      ]
    }
]

例では gs:// から始まっていますが、これは Google Cloud Storage(GCS) のバケット上のファイルです。実際には実行時に CSV ファイルを実行環境の TMPDIR 以下にダウンロードするので、ローカルストレージに十分な空きがあるかに注意ください。
ローカルのファイルを直接指定することも可能です。

注意点

日付形式

ドキュメントにはタイムスタンプは ISO 8601 を受け取るとありますが、実装を見る限り strftime("%Y-%m-%d %H:%M:%S") という文字列を受け取ります。
お手数ですが、事前に変換などを行ってください。

NULL の取り扱いについて

CSV はテキスト形式であるため、RDBMS の NULL に当たる概念がありません。デフォルトでは空文字列を NULL として取り扱います。特定の文字列を NULL として取り扱って欲しい場合には -source-profile の引数として nullstr を指定してください。上記の例では NULL という文字列を NULL 扱いするように指定しています。

エラーログについて

実行時は標準出力と標準エラー出力に様々な情報を出力しますが、上手くインポート出来ない場合にはエラーレベルを上げて実行すると手がかりになる情報が得られる場合があります。デバッグレベルを指定するにはオプションとして -log-level DEBUG などと指定すると良いです。

テンポラリファイル

GCS からダウンロードした一時ファイルは TMPDIR 以下に置きます。このディレクトリが十分な空き容量があることを確認ください。 が、TMPDIR の末尾が / で終わることを期待した実装になっています。この動作については柔軟性が低いと思われるため(環境変数を “/tmp” とすると意図した通りに動作しないなど) 、-- 修正の Pull Request を用意する予定です。 https://github.com/cloudspannerecosystem/harbourbridge/pull/396 マージされました

インポート速度

1000 PU(1 node)の Cloud Spanner に対して、上記のサンプルテーブルへ100万行の CSV ファイルをインポートしたところ、10 から 12秒程度で実行完了しました。

Discussion

ログインするとコメントできます