Daily Cost
$139
+73% vs 30d ago
Monthly Est.
~$4,050
約60万円/月
MERGE Share
95%
$132 / $139
Daily Scan
22 TB
28施設 x ~40テーブル
Data Pipeline
Step 3 にボトルネック
1
PMS(FrontCrew)- 各ホテル
全国 28施設 のホテル管理システムから、宿泊・売上・予約などのデータを毎日CSV出力
2
Google Cloud Storage
ホテルごとの専用バケットにCSVをアップロード。コスト問題なし。
3
Cloud Functions → BigQuery MERGE $132/日 = 95%
毎晩 02:00 JST に自動実行。28施設 x 約40テーブル = 約1,150回のMERGE。
問題: テーブルにクラスタリングがないため、1施設のMERGEで全施設の全データをフルスキャン。
たとえると: 図書館でAホテルの本を1冊棚に戻すために、毎回すべての本を床に出して並べ直している状態。本が増えるほど作業量が増える。
4
dbt(集計・加工)$3.5/日
統合データをレポート用に集計・変換。コスト正常。
5
Looker Studio / スプレッドシート
レベニュー・稼働分母・売上明細・カスタマイズシートに出力。$2.7/日。
Cost by Source
MERGE
95%
$132
dbt
$3.5
Users
$2.7
Cost by Account
cf-sa (CF)
$132
$132
dbt-sa
$3.5
iwamoto
$1.9
others
$1.3
Top Tables by Cost
上位5テーブル = 76%
御客伝票 (188GB)
3.5億行 / 28 merges
$32
御客情報 (132GB)
9,400万行
$22
御客伝票B (113GB)
2億行
$19
御客詳細 (82GB)
4億行
$14
御客GR (77GB)
6,100万行
$13
BigQueryは「読んだデータ量」で課金($6.25/TB)。御客伝票 188GB x 28施設 = 5.3TB/日 → $33/日。40テーブル合計で約22TB/日。
30-Day Cost Trend
+73%
$160 $120 $80 $40 $0 $81 $139 3/3 3/13 3/23 4/1
放置リスク: 施設追加+データ蓄積の二重増加。半年後に$200+/日の見込み。レポート月額(2〜3万/施設)を考えると利益を圧迫。
30-Day Cost Trend
+73%
$160 $120 $80 $40 $0 $81 $139 3/3 3/13 3/23 4/1
放置リスク: 施設追加 + データ蓄積の二重増加。半年後に$200+/日(月9万円増)の見込み。レポート月額(2〜3万/施設)を考えると利益を圧迫する水準。
現在
~$4,050/月
約60万円
改善後
~$450/月
約7万円(90%減)
おすすめ

A. クラスタリング追加

85〜90%削減
テーブルに hotel_id の索引を追加。MERGEで該当施設のデータだけ読むようになる。CF側のコード変更不要。
中 / 1〜2日
詳細手順

B. 定額プラン

~75%削減
従量制→月額固定。月$960〜1,200。携帯のギガ放題と同じ考え方。処理速度がやや遅くなる可能性あり。
低 / 即日

C. 差分MERGE

5〜50%削減
変更データだけ更新する方式に変更。効果はデータ更新頻度次第。CF側のコード変更が必要。
高 / 2〜3日
現実的

D. 段階実施

最大90%+
即日: B で出血止め → 1〜2日: A を上位5テーブルに → その後: 定額解約 or 縮小
Step1即日 / Step2 1〜2日
Overview
CF側コード変更不要
削減効果
85〜90%
作業時間
1〜2日
コード変更
不要
リスク
What & Why
今の問題: テーブルに整理がない。1施設のMERGEで全28施設の全データをフルスキャン → 1日$132。
やること: テーブルに hotel_id のクラスタリング(索引)を追加。MERGEで該当施設だけ読むようになる。スキャン量 22TB → 1〜2TB。
コード変更不要の理由: MERGEのSQLに既に hotel_id が条件に含まれている。BigQueryが自動的にクラスタを利用してスキャン削減する。stable社のコードは一切触らなくてよい。
対象テーブル(優先5テーブル)
全体の76%
# テーブル 本番 行数 Cost/日 staging MERGEキー
1be_D_御客伝票188 GB3.5億$31.832.82 GBhotel_id, 明細番号, 行, レコード更新日
2be_D_御客情報132 GB9,400万$22.301.96 GBhotel_id, 御客番号, レコード更新日
3be_B_御客伝票113 GB2.0億$19.221.73 GBhotel_id, 集計日, 明細番号, 行, ...
4be_D_御客詳細82 GB4.0億$13.971.17 GBhotel_id, 御客番号, レコード更新日
5be_D_御客GR77 GB6,100万$12.981.17 GBhotel_id, グループ番号, レコード更新日
合計592 GB11.5億$100.308.85 GB
全テーブルのMERGEキーの先頭が hotel_id。 クラスタリングキーに hotel_id を指定すれば、約90テーブルすべてで効果がある。
Step 1: staging で検証
staging は本番の1/60程度のサイズ。数分で完了。
-- 1. クラスタリングつきの新テーブルを作成
CREATE TABLE `bb-frontcreue.staging_frontcrew_data.be_D_御客伝票_clustered`
CLUSTER BY hotel_id
AS SELECT * FROM `...be_D_御客伝票`;

-- 2. 旧テーブルをリネーム
ALTER TABLE `...be_D_御客伝票` RENAME TO be_D_御客伝票_old;

-- 3. 新テーブルを正式名に
ALTER TABLE `...be_D_御客伝票_clustered` RENAME TO be_D_御客伝票;

-- 4. バッチ確認後に旧テーブル削除
DROP TABLE `...be_D_御客伝票_old`;
上記を5テーブル分実行 → 翌日バッチの正常動作を確認 → 本番へ
Step 2: 本番テーブル再作成
日中に実施
タイミング: 深夜バッチ完了後〜翌日バッチ開始前(日中)に実施。リネーム中にMERGEが走ると競合するため。
1テーブルあたりの手順
A
CLUSTER BY hotel_id で新テーブル作成
元テーブルの全データをコピー + クラスタリング適用。188GBで数分〜15分。
B
テーブル名を入れ替え(2つのRENAME)
旧→_old、新→正式名。即時完了(メタデータ変更のみ)。
C
翌日バッチ確認後、旧テーブル削除
確認できるまで _old は残す(ロールバック用バックアップ)。
-- ========== be_D_御客伝票 (188GB) ==========
CREATE TABLE `bb-frontcreue.production_frontcrew_data.be_D_御客伝票_clustered`
CLUSTER BY hotel_id AS SELECT * FROM `...be_D_御客伝票`;
ALTER TABLE `...be_D_御客伝票` RENAME TO be_D_御客伝票_old;
ALTER TABLE `...be_D_御客伝票_clustered` RENAME TO be_D_御客伝票;

-- ========== be_D_御客情報 (132GB) ==========
CREATE TABLE `...be_D_御客情報_clustered`
CLUSTER BY hotel_id AS SELECT * FROM `...be_D_御客情報`;
ALTER TABLE `...be_D_御客情報` RENAME TO be_D_御客情報_old;
ALTER TABLE `...be_D_御客情報_clustered` RENAME TO be_D_御客情報;

-- ========== be_B_御客伝票 (113GB) ==========
CREATE TABLE `...be_B_御客伝票_clustered`
CLUSTER BY hotel_id AS SELECT * FROM `...be_B_御客伝票`;
ALTER TABLE `...be_B_御客伝票` RENAME TO be_B_御客伝票_old;
ALTER TABLE `...be_B_御客伝票_clustered` RENAME TO be_B_御客伝票;

-- ========== be_D_御客詳細 (82GB) ==========
CREATE TABLE `...be_D_御客詳細_clustered`
CLUSTER BY hotel_id AS SELECT * FROM `...be_D_御客詳細`;
ALTER TABLE `...be_D_御客詳細` RENAME TO be_D_御客詳細_old;
ALTER TABLE `...be_D_御客詳細_clustered` RENAME TO be_D_御客詳細;

-- ========== be_D_御客GR (77GB) ==========
CREATE TABLE `...be_D_御客GR_clustered`
CLUSTER BY hotel_id AS SELECT * FROM `...be_D_御客GR`;
ALTER TABLE `...be_D_御客GR` RENAME TO be_D_御客GR_old;
ALTER TABLE `...be_D_御客GR_clustered` RENAME TO be_D_御客GR;

-- ========== バッチ確認後に旧テーブル削除 ==========
-- DROP TABLE `...be_D_御客伝票_old`;
-- DROP TABLE `...be_D_御客情報_old`;
-- DROP TABLE `...be_B_御客伝票_old`;
-- DROP TABLE `...be_D_御客詳細_old`;
-- DROP TABLE `...be_D_御客GR_old`;
CREATE TABLE の課金: 5テーブル合計 592GB = 約$3.7の一時コスト。削減効果($100+/日)に比べれば問題なし。
Step 3: 効果確認
-- 翌日バッチ後に実行
SELECT DATE(creation_time) AS date,
  COUNT(*) AS jobs,
  ROUND(SUM(total_bytes_billed)/POW(1024,4), 2) AS tb,
  ROUND(SUM(total_bytes_billed)/POW(1024,4)*6.25, 2) AS cost_usd
FROM `region-asia-northeast1`.INFORMATION_SCHEMA.JOBS
WHERE creation_time >= TIMESTAMP('YYYY-MM-DD')
  AND job_type = 'QUERY' AND state = 'DONE'
GROUP BY date;
スキャン量が 22TB → 1〜2TB に減っている
コストが $139 → $15〜20 に減っている
バッチの処理時間が大幅に遅くなっていない
確認OKなら _old テーブルを削除
問題発生時のロールバック: 旧テーブル(_old)をRENAMEで元に戻すだけ。即時復旧(データコピーなし)。
Confirmed
Cloud Functions管理: stable社
バッチは深夜のみ → 日中の作業で競合なし
staging環境での事前検証 → OK
stable社への依頼
1
staging で検証
上位5テーブルにクラスタリング(hotel_id)を追加。翌日バッチの正常動作を確認。
2
本番の上位5テーブルを日中に再作成
be_D_御客伝票 / be_D_御客情報 / be_B_御客伝票 / be_D_御客詳細 / be_D_御客GR
5テーブルで全体コストの76%($100/日)。
3
翌日バッチ結果を確認
スキャン量 22TB → 2〜3TB に減っていればOK。コスト $139 → $15〜20/日。