Cloud SpannerからAvro経由でBigQueryにデータのExport Import

SpannerのデータをBigQueryに取り込む方法です。基本は以下の2つの内容を組み合わせます。

cloud.google.com

cloud.google.com

簡単に図にするとこんな感じです。

f:id:yomon8:20200129085143p:plain

Dataflowジョブの登録

今回利用するのはGoogle製のテンプレートジョブです。ちゃんとSpannerからスキーマ情報等を引き抜いてAvroを作ってくれます。調整したい場合もこのコードを元に調整すると早そうです。

https://github.com/GoogleCloudPlatform/DataflowTemplates/blob/master/src/main/java/com/google/cloud/teleport/spanner/ExportPipeline.java

GCPの既製のテンプレートは gs://dataflow-templates/latest/ に保管されているので、これをDataflowで呼び出します。

SPANNER_INSTANCE="spanner-instance-name"
SPANNER_DB="source_db_name"
JOB_NAME="export_spanner_${SPANNER_INSTANCE}_${SPANNER_DB}_$(date +%Y%m%d_%H%M%S)"
TEMPLATE_LOCATION="gs://dataflow-templates/latest/Cloud_Spanner_to_GCS_Avro"
OUTPUT_LOCATION="gs://otomo-spanner-exp/avro"
STAGING_LOCATION="gs://otomo-spanner-exp/temp"
REGION="asia-northeast1"

gcloud dataflow jobs run ${JOB_NAME} \
  --gcs-location=${TEMPLATE_LOCATION} \
  --region=${REGION} \
  --staging-location=${STAGING_LOCATION} \
  --parameters=instanceId=${SPANNER_INSTANCE},databaseId=${SPANNER_DB},outputDir=${OUTPUT_LOCATION}

実行すると、ジョブの情報が表示されます。

createTime: '2020-01-29T00:26:17.983241Z'
currentStateTime: '1970-01-01T00:00:00Z'                                                                             
id: 2020-01-28_16_26_15-11984201559070487438
location: asia-northeast1
name: export_spanner_xxxx_xxxxx_20200129_092614
projectId: your_project
startTime: '2020-01-29T00:26:17.983241Z'
type: JOB_TYPE_BATCH

この出力の id 部分が揃うと、出力先のディレクトリが特定できます。

JOB_ID=2020-01-28_16_26_15-11984201559070487438
AVRO_DIR="${OUTPUT_LOCATION}/${SPANNER_INSTANCE}-${SPANNER_DB}-${JOB_ID}"

Dataflowの画面でもジョブが実行されているのが見られます。

f:id:yomon8:20200129092232p:plain

f:id:yomon8:20200129092444p:plain

ジョブが完了すると、指定したバケットにAvro形式のデータが吐かれます。

f:id:yomon8:20200129093520p:plain

このディレクトリの下に、例えばDatabaseに入っているのが、SingersとUsersのテーブルの場合は以下のようにAvro形式のデータと、JSON形式のManufestファイルがExportされます。

   Singers-manifest.json
   Singers.avro-00000-of-00002
   Singers.avro-00001-of-00002
   Users-manifest.json
   Users.avro-00000-of-00003
   Users.avro-00001-of-00003
   Users.avro-00002-of-00003
   spanner-export.json

bqコマンドでAvroをロード

GCS上にあるAvroをBigQueryにロードします。

DATASET="otomo_ds"

bq mk --location asia-northeast1 ${DATASET}

今まで定義してきた変数を使いながら、読み込むテーブル名のリストを並べてxargs使って並列で、bqでロードジョブ流し込んでみます。Avroはスキーマ情報を保持しているので、こちらから渡してあげる必要が無く、オプションはシンプルになります。

AVRO_DIR="${OUTPUT_LOCATION}/${SPANNER_INSTANCE}-${SPANNER_DB}-${JOB_ID}"

cat <<EOT | xargs -P 4 -Ixxx bq load --source_format=AVRO ${DATASET}.xxx "${AVRO_DIR}/xxx.avro*"
Singers
Users
TableA
TableB
TableC
EOT

これでデータがロードされてBigQuery側でも、データをクエリすることができるようになりました。