· ハルボウヤ · dataflow · 9 min read

KARTEとGCPの連携が、運用に入ってから壊れる場所

遅延データ、重複、テーブル名の不一致、スキャン量。KARTE Datahub とBigQueryの連携を運用し続けるときに効いてくる勘所を整理する。

運用でつまずく4箇所を示した図。遅延データ、重複、名前の不一致、スキャン量の4項目が並んでいる

データ連携は、作った直後は動く。壊れるのは運用に入ってから。しかも壊れても業務は止まらないため、発覚が遅れる。

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 のライフサイクルは、最初に設定して忘れる

連携は、作るより維持するほうが長い。壊れたことに気づける仕組みを、作るときに一緒に入れておく。

Share:
Back to Blog

Related Posts

View All Posts »