1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[BigQuery] bq コマンドでテーブルの種類ごとにコピー方法を整理してみた

Posted at

はじめに

BigQuery のデータ移行やステージング環境へのコピー作業において、テーブルの種類によって bq コマンドの使い方が異なることに気づきました。

この記事では、次の 4 種類のテーブルごとにコピー方法をまとめています:

  • Standard Table(通常のテーブル)
  • View(ビュー)
  • External Table(外部データ構成テーブル)
  • Materialized View(マテリアライズドビュー)

通常テーブルのコピー

単一テーブルのコピー

#!/bin/bash

SRC_PROJECT="source-project"
DEST_PROJECT="destination-project"
LOCATION="us"

DATASET="example_dataset"
TABLE="example_table"

# すでに存在する場合はスキップ
if bq show --project_id="$DEST_PROJECT" --format=prettyjson \
     "${DEST_PROJECT}:${DATASET}.${TABLE}" > /dev/null 2>&1; then
  echo "[SKIP]  Table already exists: ${DATASET}.${TABLE}"
else
  bq cp --force --location="$LOCATION" \
    "${SRC_PROJECT}:${DATASET}.${TABLE}" \
    "${DEST_PROJECT}:${DATASET}.${TABLE}" > /dev/null 2>&1

  if [ $? -eq 0 ]; then
    echo "[OK]    Table copied: ${DATASET}.${TABLE}"
  else
    echo "[WARN]  Failed to copy table: ${DATASET}.${TABLE}" >&2
  fi
fi

複数テーブルのコピー

#!/bin/bash

SRC_PROJECT="source-project"
DEST_PROJECT="destination-project"
LOCATION="us"

TABLES=(
example_dataset.table1
example_dataset.table2
example_dataset.table3
)

for FULL_TABLE in "${TABLES[@]}"; do
  DATASET=$(echo "$FULL_TABLE" | cut -d'.' -f1)
  TABLE=$(echo "$FULL_TABLE" | cut -d'.' -f2)

  if bq show --project_id="$DEST_PROJECT" --format=prettyjson \
       "${DEST_PROJECT}:${DATASET}.${TABLE}" > /dev/null 2>&1; then
    echo "[SKIP]  Table already exists: ${DATASET}.${TABLE}"
  else
    bq cp --force --location="$LOCATION" \
      "${SRC_PROJECT}:${DATASET}.${TABLE}" \
      "${DEST_PROJECT}:${DATASET}.${TABLE}" > /dev/null 2>&1

    if [ $? -eq 0 ]; then
      echo "[OK]    Table copied: ${DATASET}.${TABLE}"
    else
      echo "[WARN]  Failed to copy table: ${DATASET}.${TABLE}" >&2
    fi
  fi
done

既存テーブルを上書きしたい場合

#!/bin/bash

SOURCE_PROJECT="source-project"
TARGET_PROJECT="destination-project"

TABLES=(
"dataset1.table_a"
"dataset2.table_b"
"dataset2.table_c"
)

for table in "${TABLES[@]}"
do
  echo "Copying ${table}..."
  bq cp --force=true "${SOURCE_PROJECT}:${table}" "${TARGET_PROJECT}:${table}"
done


View(ビュー)のコピー

View は bq cp ではコピーできませんが、SQL を再定義すれば作成できます。

#!/bin/bash

DEST_PROJECT="destination-project"
DEST_DATASET="example_dataset"
DEST_VIEW="example_view"
LOCATION="us"

bq mk \
  --use_legacy_sql=false \
  --location="${LOCATION}" \
  --view '
    SELECT * FROM `source-project.example_dataset.example_table`;
  ' \
  "${DEST_PROJECT}:${DEST_DATASET}.${DEST_VIEW}"

外部データ構成テーブル(External Table)のコピー

外部テーブルは bq cp でコピーできないため、通常テーブルとして SELECT 結果を書き出す形でコピーします。

#!/bin/bash

SRC_PROJECT="source-project"
SRC_DATASET="external_dataset"
SRC_TABLE="external_table"

DEST_PROJECT="destination-project"
DEST_DATASET="internal_dataset"
DEST_TABLE="copied_table"
LOCATION="us"

echo "[INFO] Copying external table to internal table..."

bq query \
  --use_legacy_sql=false \
  --location="${LOCATION}" \
  --destination_table="${DEST_PROJECT}:${DEST_DATASET}.${DEST_TABLE}" \
  --replace \
  "SELECT * FROM \`${SRC_PROJECT}.${SRC_DATASET}.${SRC_TABLE}\`"

if [ $? -eq 0 ]; then
  echo "[OK]   External table successfully copied to internal table."
else
  echo "[ERROR] Failed to copy external table." >&2
fi

Materialized View(マテリアライズドビュー)のコピー

Materialized View は bq cp ではコピーできません。

❌ NG 例:

bq cp source-project.dataset.mv destination-project.dataset.mv
# → エラーになる

✅ OK:SQL 定義を再利用して bq mk で作り直す


#!/bin/bash

SRC_PROJECT="source-project"
DEST_PROJECT="destination-project"
DATASET="example_dataset"
VIEW_NAME="example_mv"
LOCATION="us"

QUERY='
SELECT
  *
FROM
  `source-project.example_dataset.source_table`
WHERE
  column_name LIKE "%pattern%"
'

# 既存の View を削除(必要に応じて)
if bq show --project_id="${DEST_PROJECT}" "${DATASET}.${VIEW_NAME}" > /dev/null 2>&1; then
  echo "[WARN] View already exists: ${DEST_PROJECT}.${DATASET}.${VIEW_NAME}"
  bq rm -f -t "${DEST_PROJECT}:${DATASET}.${VIEW_NAME}"
fi

Materialized View を作成

bq mk \
  --materialized_view \
  --view_query="$QUERY" \
  --use_legacy_sql=false \
  --location="$LOCATION" \
  --time_partitioning_field="partition_column" \
  --clustering_fields="cluster_column" \
  "${DEST_PROJECT}:${DATASET}.${VIEW_NAME}"

if [ $? -eq 0 ]; then
  echo "[OK]   Materialized view created successfully."
else
  echo "[ERROR] Failed to create materialized view." >&2
fi

おわりに

BigQuery のテーブルをコピーする際、テーブルの種類に応じて最適な方法を選ぶことが大切です。

特にステージング環境などにおいて、bq コマンドを活用すれば、簡単かつ柔軟にコピー作業を行うことができます。

参考になれば嬉しいです!

🗒️ 他にも便利な BigQuery Tips があればぜひコメントで教えてください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?