プロダクトの集計機能をdbtに置き換えた導入話
こんにちは。
これはdbt Advent Calendar 2023 15日目の記事です。
普段からデータ基盤でdbtを使ってますが、今回は自社で開発するプロダクトの「集計/アナリティクス機能」にdbtを輸入してみたというお話です。技術的な話はしません。
背景
この物語は、今から約2年前に遡ります。
- アナリティクス画面で集計してる指標を顧客ごとに見たいという要望あり
- プロダクトと同じロジックをデータ基盤側で実装し、Lookerで可視化した
- ※データ基盤のデータソース参照元の制約があるので、プロダクトの集計結果をそのまま基盤に引っ張れない
- アナリティクス画面とLookerで、各指標に微妙に数値の差分があるよとCSチームから疑問が
- 例えば◯月の◯◯利用率が、33.5%が33.2%になってる
- サーバーサイドエンジニアに問い合わせてみるが、集計SQLがぐちゃぐちゃで考古学状態になっており、調査工数結構かかる
- この過程で一部微妙にバグってるもの発見される
- なんで我々こんな苦労してるんだっけ
- 小数点数%の誤差って、CSチームが下す意思決定にどれぐらい寄与するのだろうか?ぶっちゃけ関係なくね? → わかる
- とはいえ同じ指標と言われているのに、数値が違ったら気になるじゃん → わかる
- このやりとりが、定期的にそこそこ発生するの、なんかおかしくね? → わかる
- じゃレポートサービス管轄のDBをデータ基盤が参照する? → プロダクトとデータ基盤の依存関係的に無し
- 根本何が良くないか考えた時に、プロダクト側のアナリティクス画面のSQLが開発保守出来ない状況がよくないのでは? → それだ
プロダクトの保守運用問題が、将来の我々データ基盤の首を締める気がする、なんとかしなきゃ!
プロダクト側の課題
- どんな設計になってるの
- アナリティクス画面から集計リクエスト → cloudbuild経由で600行ぐらいのSQLが頑張ってデータを引っ張る → CSV化みたいなイメージ
- とにかく欲しい情報をめっちゃかき集めてjoin join joinみたいな感じ、それが1機能600行ずつあるイメージ
- なんでこうなってるの
- 恐らく当時、アナリティクス機能を急いで提供する必要がある → 当時頑張った
- 追加機能があると、その魔窟SQLにSQLを付け足すことになる
- アナリティクス画面って機能アップデートの頻度が低いので、手を加えることも見る頻度も少ない
- 当時開発してたメンバーはほぼ卒業してしまい、ドキュメントも残ってないので背景、意図、仕様がわからないまま今に至る
まぁ、あるある話ですね、何れにせよ課題感はわかった!
プロダクト側へ改善の打診
- 開発チームではないですが、アナリティクス機能のリファクタしませんか?とこちらから打診
- 上記の課題感を伝えてたが、現実問題難しそう
- ◯◯対応や◯◯機能開発で、エンジニアのリソースがパッツパツ
- 現状ってアナリティクス画面が問題なく動いているよね?
- これって今の事業課題に対して事業インパクト小さいのでは?
確かに。技術的負債あるある話ですが、これに関しては実際通りだと思った。断念!
だが俺は諦めない!1年後でもいいから改善の動きを作りに行ってやる🔥
dbt導入プロセス
①機運を高める
- プロダクトのサーバーサイドエンジニアが主催する勉強会に定期的に参加しました
- 技術的に面白いから、みんなも興味持ってね〜的なスタンスで話してました
- てか去年記事書いてましたわ。サーバーサイドエンジニアにdbtを宣伝したお話です
- 「データ基盤の知見をプロダクト方面にも還元出来ると思っているので、2023年はそのあたりを目論んでます」で締めてますね
- あくまでも勉強会での技術共有なので、興味持ってくれた人いたらラッキーぐらいのノリで
- なんかわからんけどdbtって便利らしい、ゲンシュンはdbt好きらしい、ぐらいの認知を得る
②追い風になる瞬間を逃すな
1年が経過しました。
- 集計の解読つらいよ〜、キレイに直したいよ〜という嘆きをslackで見かける
- 俺「dbtをプロダクトに導入出来たら、この課題ある程度解消できそうだけどな〜|д゚)チラッ」
- 開発メンバー「オッ!?ちょっと気になるんだが」
- この話とは別に、今後アナリティクス画面を機能拡張したい構想があると聞く
- まさに、アナリティクス画面のSQL改善したいやつじゃん
キタ━━━━(゚∀゚)━━━━!!
ということでサーバーサイドエンジニアに、dbtをインプットしてプロダクトへ輸入できないか?の検証PJ開幕。これが今からちょうど半年前です。
たまたまですが、新卒からの同期です。一緒に仕事するのなんだかんだ初なのでアツい。
③検証として小さく始める
このプロセスが一番大事でした。
- dbtとは何かを知ってもらう
- 公式ドキュメント見ながら、何か簡単目の機能を1個置き換えてインプットしようと構想
- しかし、同期が超優秀で自分でdbt触って勝手に習得してしまったので、inputほぼやってない笑
- 自分からは、データ基盤での実例や便利機能などを補足してただけ
- ランニングコストが低いのがメリットでした
- 課題感のすり合わせ
- 課題の言語化と解決したい課題をどこまでdbtに解決させたいか?をざっくり議論
- 可読性低い、仕様がわからない、テストがやりづらい、パフォーマンス悪そう、顧客や社内からの問い合わせに膨大な工数(考古学)、などが課題としてあがる
- 「アナリティクス画面の機能拡張に対し、デリバリを高速化したい」「ドメイン構造を整理」「テストしやすい」の3つぐらいにまとまる
- dbt導入で開発メンバーはどんな恩恵受けられそう?
- dbtは万物を解決する神ではないので、何が得られるのか検証対象を洗い出すために話しました
- モデリングでドメインの整理が出来そう、可読性高くなりそう、共通処理の共通化得意そう、中間テーブルとか良さそう、テストや仕様の記載が楽そう、知見が多そうなど
- 「データ基盤チームが既に持ってる知見を、サーバーサイドメンバーに普及されることで、諸々win-winになりそう」「テスト実行容易性」あたりですかね〜
- AS ISとTO BEの整理
- なんだかんだこの半年、ここに何度も立ち戻りました
- 何のために導入するんだっけ?何の課題をまず解決したいんだっけ?を何度も話しました
- ここがブレると、実装方針や検証範囲が揺らいじゃうので、定期的に立ち止まって話しました
- 目的とスコープを定める
- 検証期間は2ヶ月前後を想定、2ヶ月後に「導入する」「しない」の判断を下す
- 目的はプロダクトへdbt導入する際に想定される懸念事項を潰し、必要な品質担保得られるかを検証
- テストデータの作成やクエリコストの削減は、検証の優先事項から外す
- beforeSQLとafterSQLのコスト差の算出などはやってません
- 仮に算出してコストがdbtの方が上がっちゃいました、となった場合dbt導入しない判断になるんだっけ?
- 集計データせいぜい数GBなので、ぶっちゃけ大したコストにならない(はず)
- 検証ゴールまでのロードマップ立てる
- 実行手段はどうにでもなりそうなので、最後に後回し
- 考古学の開始
- まず集計機何種類ある?
- どんなデータ(activeなユーザだけ集計?など)が対象?
- 最終的なアウトプットってどういう単位でやってる?daily?monthly?
- 考古学は1人では絶対厳しかった、一緒に闇SQLを読んでよかった助かったぜ
- 1機能をdbtで置き換えてみる
- ここからずっとペアプロ作業
- 自分ではある程度設計や実装のイメージはもつが、基本開発メンバーに実装してもらう
- 命名規則、ディレクトリ名(stgやmartは不適切)、SQLフォーマットなど全部後回し
- モデリング作業、実装、動作確認を延々と反復横跳び
- たくさんの発見があって楽しかったです、些細なバグや深淵の闇との出会いもありました
- documentをちゃんと書く
- ymlに仕様書いて、担保したいテストを記載。この仕様なんだっけ?が即わかるのありがたい
- dbt docsで色々依存関係が把握できるのイケてる(ウケが良かったです)
- テスト観点
- アナリティクス機能として必要なテストの洗い出し(NOT NULLやUNIQUEなど)
- stg環境でどうやって動作確認を担保するか議論
- 負荷やデータ量をある程度見積もって、リリースへの影響が無さそうと判断
2ヶ月の軽い検証を経て、これは導入できるぞ!と判断。ペアプロ形式で1日30分、週2時間と日進月歩で掴んだ勝利です
④考古学の過程で厳しい既存仕様を発掘
とある集計仕様のせいで、実装の複雑性を500倍にしてるものを発掘しました。ダークマターです。
- ある特定の日付よりも前の集計方法が独特すぎる
- アナリティクスの集計は、サービスが始まってから全期間集計可能になってる
- ほぼ全ての集計に必須なマスターデータA/Bについて、Aは2019年以前には存在せず、Bは2021年以前に存在しない、みたいな状況になってる(昔はsnapshotsを取ってなかった)
- 2019年以前の集計は、集計期間無視してAが存在する最古のデータを出力する、Bも同様(この独特仕様はヘルプページにも記載されてる)
- 実装の分岐がヤバすぎる
- まず初見で理解不能。ある過去よりもデータが存在しないことがわからない
- どんなデータに対しても
if 古くない その日付で出す else 存在しうる最古のデータを探す
みたいな実装があり、カオス
- とりあえずstg層で闇の仕様を全て吸収する実装をしてみる
- アプリケーション側は過去のデータの存在有無は気にせず、内側に関心事を閉じることはできそう
- ぶっちゃけ、この仕様がなくなれば平和じゃね?存在するデータを集計すればよくね?
俺は立ち上がった。この仕様を変えねば。
⑤dbt導入に伴い機能を一部閉じることを打診
上記の例で言うならば、理想はA/B共に存在する日付以降にしたかったです。が、以下諸々考慮して「2019年以前を集計不可にしたい旨」で打診しました。
- プロダクトのGMに相談
- 論点として「顧客がほぼ利用しない(と思われる)仕様は、弊社のエンジニアを苦しめてるだけ」「解約に寄与しない」の2点を持っていく
- 顧客の利用状況と影響度合いを伝える
- 2019年以前から契約されてる顧客リスト(全体の◯%)を提示
- CSチームに直近2年よりも過去遡ってアナリティクス集計するかヒアリングしたが、無かった
- 4年以上前の状態をわざわざ見る人って居るのかしら?居ないんじゃね(これは主観的意見)
- ※データ基盤側で集計期間も取れれば説得性増したんですけど、集計回数しか取れなかったです(泣)
- データが物理的に削除されるわけではないこと、一部の集計機能の集計期間を狭めてるだけであることを伝える
- Bが無いよという話も伝える、これは数年後に判断にしましょうと合意
- 温度感良さそう
- 顧客問い合わせを受けるであろうCSやテクニカルサポートチームに、方針と仕様変更後をアナウンス
- 集計期間を狭める対応ってdbt導入有無関係ないと自分は判断したので、先に画面を閉じるリリースをしてから、安全にdbtリリースする方針で
- このあたりも、各方面に相談して順番にリリース出来たので良かったです、対話大事!
これにより、変な仕様を削除しシンプルな集計ルールに!ありがとう!
今回はある程度わかりやすい例で流れを説明しましたが、これに伴って他にも何点か仕様を変更しました。 考古学 モデリングによって色々明らかに出来たのが良かったです。
dbt導入の感想
- 良かったこと
- dbt docsで、テーブルの依存関係やデータフローが可視化されてわかりやすい
- ymlにデータの仕様とテストがセットで出来る
- 毎日dbt testが走ることの安心感
- モデリングにより、既存の仕様を紐づきやすかった
- 苦労したこと
- リソース調達。検証終了後に1~2ヶ月ぐらいサーバーサイドメンバー巻き込んで実装進める想定だったが、パツパツだったので結局同期2人で最後までやり切ることに
- テスト関連。stg環境のデータが欠損が多く、本来は動くけどstgではtest通らない〜が連発
伝えたいこと
- 今回遭遇した様々な事象って、世の中的にあるあるだと思うんですよ
- 前任者不在で仕様と背景と意図が誰もわからない
- 開発リソース無くて技術的負債解消への優先度が上げられない
- 顧客にメリットがあまり無い仕様のせいで、実装が複雑化してる
- でも、諦めずいろんな人と対話して意図を説明して機運(優先度が上がる)を見計らうのが大事だと思ってます
- 目的を見失わないこと
- AS ISとTO BEの整理 ここに何度も立ち戻りました
- 色々長いことやってると、何のためにこれやってるんだっけ?になりやすいです
- 今回の負債解消はdbtでなければ実現できなかったのか?
- こんな記事書いてますが、正直そんなことはないです笑
- やったことをシンプルにまとめると「SQLを書き直す」「一部の仕様変更」だけです
- ただ、dbtは強力且つランニングコスト低い武器なのでワクワクしやすい、これって賛同者や仲間を得られやすいポイントだと思ってます
- そんな「機運」を作ってくれたdbtありがとう、俺にはお前しか居ねぇ
なんだかんだ検証と本導入に約半年間、うすーくながーいPJとなりましたが、一緒に並走してくれた同期、そしてdbtに本当に感謝です!
以上です。ありがとうございました!
Discussion