はじめに
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 があればぜひコメントで教えてください!