· ハルボウヤ · dataflow · 9 min read
KARTEとGCPの連携が、運用に入ってから壊れる場所
遅延データ、重複、テーブル名の不一致、スキャン量。KARTE Datahub とBigQueryの連携を運用し続けるときに効いてくる勘所を整理する。

データ連携は、作った直後は動く。壊れるのは運用に入ってから。しかも壊れても業務は止まらないため、発覚が遅れる。
KARTE Datahub と BigQuery の連携で、実際に効いてくる勘所を整理する。前提となる構成の決め方は別の記事で扱っているので、ここでは運用の話に絞る。
1. 当日のデータは揃わない前提で組む
行動ログは、その日のうちに全部が確定するわけではない。ネットワークの都合で遅れて届くもの、集計側の処理が終わっていないものがある。
深夜0時に前日分を取りに行くと、取りこぼす。
対処は2つ。
取得タイミングを遅らせる。前日分を朝に取りに行く。ただし遅らせるほど、レポートの鮮度は落ちる。
過去分を定期的に取り直す。前日分に加えて、3日前から7日前までを毎日上書きし直す。遅れて届いたデータが後から埋まる。
後者を採るなら、Append ではなく日付パーティション単位の Overwrite が必須になる。Append で取り直すと、そのまま重複する。
2. 重複と欠損は、別々に検知する
連携の事故は2方向ある。
| 事故 | 症状 | 気づきやすさ |
|---|---|---|
| 欠損 | 件数が減る、0件になる | 気づきやすい |
| 重複 | 件数が増える | 気づきにくい |
件数が増えているとき、人は「良いこと」だと思って見過ごす。売上が伸びたのか、二重計上なのか、数字だけでは判別できない。
最低限、次の2つをクエリで毎日確認する。
-- 日別の件数と、ユニークキーの重複有無
SELECT
event_date,
COUNT(*) AS rows_total,
COUNT(DISTINCT event_id) AS rows_unique,
COUNT(*) - COUNT(DISTINCT event_id) AS duplicated
FROM `プロジェクト.データセット.テーブル`
WHERE event_date >= DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 14 DAY)
GROUP BY event_date
ORDER BY event_date DESC;duplicated が 0 でなければ重複。件数が前週同曜日と大きく乖離していれば欠損の疑い。曜日で比較するのがポイントで、平日と休日を並べると常に異常に見える。
3. 名前の不一致が、引き継ぎを止める
連携が増えると、同じデータが違う名前で存在するようになる。
- 連携元(KARTE 側)での呼び名
- 取り込んだ生データ層での名前
- 加工後の名前
- BIツール上での表示名
この4つが揃っていないと、引き継ぎができなくなる。「この数字はどこから来ているのか」を追えるのが作った本人だけ、という状態になる。
対処は地味だが効果が大きい。
対応表を1枚作る。連携元の名称、生データ層のテーブル名、加工後のテーブル名、BI上の表示名を1行に並べる。スプレッドシート1枚で足りる。
命名規則を先に決める。層ごとに接頭辞を揃える(生データ層は raw_、加工層は mart_ など)だけでも、どこにあるかが名前から分かる。
構成図を残す。文章より図のほうが伝わる。矢印がつながっていることが確認できれば十分で、凝ったものは要らない。
引き継ぎのときに一番時間を取られるのは、コードを読む作業ではなく**「どれとどれが同じものか」を突き止める作業**。ここを先に潰しておく。
4. スキャン量は設計で決まる
BigQuery の課金はスキャンしたデータ量で決まる。行動ログは量が多いので、ここを外すと後から効いてくる。
日付でパーティションを切る。切っていないテーブルに WHERE event_date = ... を書いても、全件スキャンされる。逆に切ってあれば、対象日だけを読む。
CREATE TABLE `プロジェクト.データセット.テーブル`
PARTITION BY event_date
CLUSTER BY user_id
AS SELECT ...;よく絞る列でクラスタリングする。ユーザーID や施策IDなど、WHERE に頻出する列を指定する。
SELECT * を書かない。BigQuery は列単位で課金される。使わない列を読まないだけで、スキャン量が大きく下がる。
ビューの多段構成に注意する。ビューは実行のたびに元テーブルを読む。3段重ねると、元テーブルを3回読む構成になっていることがある。中間結果をテーブルとして保存したほうが安いケースは多い。
5. 失敗に気づける状態を作る
ここまでの対策は、誰かが見ていないと意味がない。
| 仕組み | 内容 |
|---|---|
| 件数の日次チェック | 上記のクエリを定期実行し、結果を通知する |
| 0件検知 | 想定より極端に少ない日を検知する |
| ジョブの失敗通知 | スケジュール実行の失敗をチャットに流す |
| 突合 | KARTE 側の管理画面の数字と、取り込んだ件数を月1回照合する |
通知先は、担当者が普段見ている場所にする。メールだと埋もれる。社内チャットに流すほうが読まれる。
通知は異常時のみにする。正常終了の通知を毎日流すと、数日で誰も読まなくなる。
6. リージョンとコストの見落とし
構成の記事でも触れたが、運用に入ってから効いてくる点として再掲する。
Datahub 側の BigQuery は US マルチリージョンにある。東京リージョンのデータセットとは直接結合できない。GCS を経由してから取り込む構成にしておくと、この制約を回避できる。
あわせて、GCS のライフサイクルルールを最初に設定する。連携用バケットにファイルが溜まり続けると、ストレージ費用が静かに増える。「30日でNearlineへ、90日で削除」といったルールを置いておけば、後から棚卸しする必要がない。
まとめ
- 当日分は揃わない。過去数日を毎日取り直す構成にする
- 欠損より重複のほうが気づきにくい。ユニークキーの重複を毎日数える
- 名前の対応表を1枚作る。引き継ぎで一番時間を食うのはここ
- パーティションとクラスタリング、
SELECT *を書かないことでスキャン量が決まる - 通知は異常時のみ。担当者が普段見ている場所に流す
- リージョンの制約と GCS のライフサイクルは、最初に設定して忘れる
連携は、作るより維持するほうが長い。壊れたことに気づける仕組みを、作るときに一緒に入れておく。



