こんにちは。開発部データエンジニアの遠藤です。現在、私はデータ×テクノロジーでZOZOグループのマーケティングを支援するデータチームに所属して、データ処理基盤の運用などに従事しています。
本記事では、Lookerを用いて運用中のデータ集計基盤をきれいなデータをスマートに取り出せる基盤に改良した件について報告します。
データ集計基盤で燻っていた問題
ZOZOでは、サービスに関するあらゆるデータをBigQueryに集約しています。BigQueryに集約した大量のデータからデータマートとして必要なデータを取り出し、BIツールの可視化や機械学習システムの入力データなどに用いています。
データマートは以下の2ステップで作成します。
【ステップ1】 ビジネス側でデータマートのアウトプットを決定・集計方法を定義
【ステップ2】 SQLを作成してデータ集計基盤にセット
データマートは、BigQueryへのマスタデータ取り込み完了後にデータ集計基盤上でクエリを順次実行して、毎日更新しています。
しかし、データ集計基盤を運用していくにつれて以下の問題が発生しました。
- クエリ管理の限界
- 集計定義に対するデータの信憑性が謎
1. クエリ管理の限界
ZOZOでは現在までに多くのデータマートが生成され、その総数は数百にのぼります。各データマートのクエリはデータ集計基盤内でファイルごとに独立、すなわち "データマートの数"="SQLファイルの数" なので、数百のSQLファイルを管理していることになります。
SQLファイルがここまで増加した背景として、車輪の再発明による量産状態になっていたことが挙げられます。データマートの作成要件があるたびにSQLを1から作り上げたため、アウトプットが似ている当時のベストエフォートクエリが複数のSQLファイルに散在していました。
また、データベースのシステム仕様に変更が生じた際、SQLファイル群から変更箇所を全て探し出して修正しなければならず、クエリの修正工数が膨大になることも問題となっていました。
そのため、クエリの効率的な管理の必要性が叫ばれていました。
2. 集計定義に対するデータの信憑性が謎
データベースのシステム仕様・ビジネス的な集計定義・データマートにおけるアウトプットは、基本的にクエリ内のSQLで表現し、それでも分かりにくい場合はクエリ内にコメントを付記することで管理していました。しかし、その管理では
- 集計仕様の把握コストの増加(クエリからそのクエリの表現に至った背景・経緯までは理解しにくい)
- 集計結果が当初取り決めた集計定義とずれる(定義に沿った集計フローに対してシステムレベルまで関係者全員の意識を合わせることは難しい)
- システム仕様変更に追随しきれない状態になると集計結果の正確性が左右される
のような問題が起きてしまいました。
その結果、「今日の数字、何か間違ってない?」と集計データに関する問い合わせが頻発し、
- (ビジネス側から見て)データ集計基盤における集計精度の信憑性を疑問視する
- (システム運用側から見て)原因調査からリカバリまでの誤集計に対する一連の障害対応の工数が膨らむ
といった誰も得しない状況に陥る恐れがありました。
そのほかにも、データ集計基盤には様々な根深い問題が存在していて、以下の図に示す内容に集約されます。
現状のデータ集計基盤では、ビジネス側で集計定義が完璧に決められていたとしても、誤った情報などが蔓延りやすくデータドリブンな意思決定の精度を下げるリスクがありました。
Lookerは何が良い? ~データガバナンス機能~
データチームは、データ集計基盤で起こる様々な根深い問題に対してシステムによる解決アプローチを模索したところ、Lookerというツールに目をつけました。LookerはLooker Data Sciences, Inc. がSaaSで提供しているBIプラットフォームです。
ビジネスインテリジェンス&ビッグデータ分析ソフトウェア - Looker
充実したReporting・Visualization機能がLookerの大きな特徴で、Lookerを国内で導入している企業のほとんどがBIツールとして使用しています。
Lookerと他のBIプラットフォームツールの相違点は様々あるのですが、ここで特筆すべき決定的に違う点…。それは…。
データガバナンス機能 です。
システム的にデータ構造を管理して正確なデータ利用を促すアプローチはLookerの唯一無二の特徴です。その特徴がLooker導入の決め手の1つになりました。
Lookerはデータガバナンス機能として以下の機能を備えています。
- LookML
- データディクショナリ
- Gitによるバージョン管理
LookML
LookerではLookMLというデータモデリング言語が採用されています。SQLに代わりLookMLで定義・集計などを記述します。
SQLは言語の特性上クエリ間の情報を転用しづらい側面がありますが、LookMLはSQLが不得意な再利用性・拡張性をカバーできます(LookMLの詳しい説明は公式ドキュメントをご覧ください)。
例えば、「テストアカウントは計上しない」という集計定義があったとします。
通常、SQLではWHERE句 WHERE member_id NOT IN (12345, 23456, 34567, 45678, 56789) -- テストアカウントは集計から省くようにする
を書きますが、LookMLではどのように書いていくのでしょうか?
まず、テストアカウントのタグ付けを行うために test_account_tag
というdimensionを定義します。
dimension: test_account_tag { case: { when: { sql: ${member_id} IN ( 12345, 23456, 34567, 45678, 56789 ) ;; label: "テストアカウント" } } }
最初に定義したdimension test_account_tag
は ${test_account_tag}
や field: test_account_tag
という表現で他の箇所で参照できます。
もしテストアカウントの member_id
構成が変更になった場合、key sql
のvalueに記されているIN句のみ修正すれば、テストアカウントに関する条件が含まれる全ての定義が変更されたことになります。
これにより、システム仕様が変更された際に生じる手間が従来のSQLファイル修正と比較すると少なくなる効果があります。
次に、テストアカウントのタグがつけられているかを示すフラグを test_account_flag
というdimensionで定義します。
dimension: test_account_flag { type: yesno sql: ${test_account_tag} = "テストアカウント" ;; }
さらに、「テストアカウントは計上しない」をkey filters
で表現します。以下のLookMLではユーザー数を集計する際にテストアカウントを除くフィルタを適用させるという定義になります。
measure: user_count { type: count_distinct sql: ${member_id} ;; filters: { field: test_account_flag value: "no" } }
このように、Lookerを用いると無機質に掃き出されたシステムデータをビジネス定義に即した意味あるデータへ変換するELTが容易にできるようになります。
また、Lookerは仮想的にデータモデルの変換・派生カラムの作成ができるので、集計途中の中間データを不必要に量産しないメリットもあります。
データディクショナリ
会員情報を表すテーブル member_info
のDDLをLookML化した一部を以下に示します。
view: member_info { sql_table_name: `zozo_original_table.member_info` ;; dimension: member_id { type: number sql: ${TABLE}.member_id ;; label: "会員ID" } dimension: resign_flag { type: yesno sql: ${TABLE}.resign_flag ;; label: "退会したか?" description: "TRUE…退会している状態\nFALSE…退会していない状態" }
上記のように、LookMLには label
description
というkeyが用意されており、これらのkeyでデータ定義をラベリングできます。データ定義をラベリングできるということはデータディクショナリとしての使用が可能であることを意味します。
開発速度がとても速いWeb開発の現場でDB定義書のようなドキュメントでメタデータ管理を行った場合、ドキュメントがシステムに追いつかない状態、つまりドキュメントとプログラムとの乖離がしばしば発生します。
Lookerは任意のデータソースに存在するテーブルの各DDLから作成した各Viewを集計フローの根幹として使用します。そのため、正確な集計を行うために最新のメタデータに更新せざるをえなくなります。
これにより、Looker内ではデータディクショナリの最新状態を保つことができます。
Gitによるバージョン管理
Lookerは、LookMLのソースコード管理にGitを採用して、ソースコードの品質を担保しています。GitHubなどのGitを用いたソフトウェア開発のプラットフォームにも連携できます。
つまり、既に運用中のGitHubと連携することで複数人開発・相互レビューといった開発体制をとることができて、データチームでもこの体制を取り入れています。
データチーム管理のデータマート作成Gitリポジトリでは、集計ガイドラインやLookMLの命名規則・記述規則といったコーディング規約を決め、互いにReviewしやすい開発体制を敷いています。
データ集計基盤(改)の設定フロー
データチームでは今回の取り組みをデータ集計基盤(改)として開発しています。データ集計基盤(改)は以下のフローでデータマート生成の設定が行われます。
まず、BigQueryに存在するテーブルのDDLをOriginal Viewとしてそのまま読み込み(《1》 スキーマ情報読み込み
)、そのOriginal View群を用いて分析に適した仮想データベースを構築します(《2》 データモデル変換
)。その仮想データベース上で必要な情報抽出から集計まで行ってデータマートViewを作成します(《3》 データマートView生成
)。
ちなみに、データ集計基盤(改)は「データマート作成のLookML内では原則SQL文完成形を直接書かない」というポリシーを持っています。つまり、SELECT … FROM …
といったSQL文を直接LookMLに入れ込むことはシステム的に可能ですが、それをあえて禁止しています。
というのも、LookerがLookMLを基にクエリを自動生成してくれるので、このポリシーがクエリ品質の均一化・データマート作成過程におけるブラックボックス化防止に繋がるためです。
データ集計基盤(改)でのデータマート更新
Lookerには好きなタイミングでアウトプットを中間データとして保存する機能が存在するのですが(PDT)、データ集計基盤(改)では、既存のデータ処理基盤との兼ね合いを考慮して、GCPの機能を用いてデータマートを更新しています。
BigQueryへのデータ取り込み完了直後にCloud Pub/SubをKickして、Cloud Functions経由でCloud Composer内のAirflow DAGを起動させます。
DAGの実行中にLooker API(Lookerが提供しているAPI)にリクエストを送り、そこからデータマート更新用クエリをレスポンスデータとして取得します。
APIで取得したクエリをBigQueryクライアントライブラリを使用したSDKを通して実行することで、各データマートに即した更新を行っています。
まとめ
Lookerを導入してデータ集計基盤の改善を図ることでデータユーティリゼーションを向上させる取り組みを報告させていただきました。
現在、データチームではデータマート更新処理をこのデータ集計基盤(改)へ順次移行している最中です。
移行中はBigQueryの最適パフォーマンスに即したLookML記法を研究してブラッシュアップしていったり…とまだ発展途上のデータ集計基盤(改)ですが、課題が徐々に解決しており、その効果も表れています。
ビッグデータを集計するシステムを運用していると、冒頭に紹介した諸問題を抱えているにもかかわらずその最適なソリューションはなかなか見つからなく、苦い思いをしている方も少なくないのかなと思います(少なくとも私は長年そう思っていた)。
この記事で快適なビッグデータのシステム運用の手助けになれば幸いです。
このように、データチームではエンジニアの強みを生かしながらデータを中心とした技術課題・マーケティング課題に取り組んでいます。メンバーを絶賛募集していますので、ご興味のある方は以下のリンクからぜひご応募ください!