SnowflakeのData Quality Monitoring機能についての考察
データ品質のモニタリングにお悩みはありませんか?
Snowflakeは他のサードパーティのソリューションをプラグインしやすいエコシステムが充実している点がいいところですが、最近はSnowflake自体が簡単なインターフェースを用意してSnowflakeだけでデータ基盤運用に必要な機能が提供されていく進化をしているように感じます。
その姿はクラウドのサービスを組み合わせてシステムを構築していく考え方に近く、まさにData Cloud (最近はAI Data Cloudですね) な訳ですが、今回は比較的地味だけど便利なData Quality Monitoringに関して、こう使ってみたらいいのではないか?という考察をしてみようと思います。
ややData Quality Monitoringに関しては捉え所が難しいところも多く、ただ機能を眺めるだけだと実践するイメージを持つのが難しいのかなと思います。そこで、この記事ではより具体的なユースケースに落とし込んで、その課題にフィットするのかどうか考えていく形で進めようと思います。
データ品質の監視という一般的な課題という事もあり、これが唯一の正解というわけではないのですが、Snowflakeが用意してくれている機能ならではの良さもあったりするので、この記事を通して面白い発見があったりすれ幸いです。
ぜひ、自分たちが携わっているプロジェクトだとどうだろうかという視点も踏まえつつ読んでみて下さい!
DMFに関しての基礎知識
詳細はこちらの検証記事などの方が詳しくまとまっているのでこちらをご覧ください。
今後の考察を解像度高く読むために主要な仕様に関してまとめていきます。
- ALTER TABLEなどのDDLでスケジュールと取得するメトリクス (DMF) に関して設定する
- Snowflakeが事前に定義したシステムDMFとユーザーが定義するカスタムDMFがある
- メトリクスはSnowflake管理のイベントテーブルに格納され、テーブル関数やビューを介してアクセス可能
- 取得したメトリクスを利用してアラートなどを設定することで通知の仕組みを構築できる
- サーバーレスコンピューティングによる課金が発生する
DMFを利用する価値があるケースについて
DMFの一番の特徴は「データの状態を自動的に一貫して測定して記録できる」です。
とはいえ、これだけだとイメージが難しいと思うので、もう少し具体的なユースケースに落としてみます。
例えば、ストリーミング的な形でデータパイプラインが組まれているようなケースを想定します。そのデータを利用して重要な施策が動いているとします。
もし、障害が起きてそのパイプラインが停止してしまうとかなりの機会損失を起こしてしまいます。
もちろんパイプライン自体にもエラーハンドリングなどの仕組みを入れていますが、パイプラインの基盤自体が落ちてしまうとエラ〜通知がうまく飛ばないケースがあり、その対策が求められているとします。
そのようなケースに対しての対策としてfreshnessやnull_countなどのメトリクスを取得してモニタリングすることでデータの遅延などの品質問題を早期に検知して対応ができるようになります。
dbtのdata testなどとの棲み分けについて
(ここからが本編です)
モダンなデータ基盤では、dbtなどを利用してELTのTransformの機能を実現するのが当たり前の世の中になってきました。その場合データ品質に関してはdbtのdata testに任せるのが一般的で実用的なプラクティスでしょう。
そのようなケースにおいてどのようにこのDMFが活用できるのか考察してみます。
dbt自体が動かない時もある
dbt data testだけに頼った場合に起こる最もクリティカルな問題としてdbt自体が実行できなくなる or 完了しないケースに対してのモニタリングです。
通常dbt data testに頼ってデータ品質を担保しているようなケースにおいてはdbt buildやdbt testなどを利用してデータ品質の問題に対処します。
このdbt実行する基盤が障害の影響を受けたり、ジョブの設定ミスなどが発生したりしてうまく動作しない場合にはエラーを検知するプロセス自体が走らなくなり、通知が飛びません。時々稀にクエリのプロファイルが最適な処理順序を通ってくれなくて処理が何倍もの時間掛かる(下手したら終わらない)ような事象も経験した人がいるかもしれません。
そういった通常は起こり得ないがたまに発生するレアケースに対しての検知の方法はなくはありません。その一つとして正常実行が完了した場合でも通知を行い「ヨシ!」を確認する方法です。
ただ、現実的には正常実行時の通知をいちいち確認するほどの余裕はなく設定される事は少ないと思います。結果として異常時の通知が届かないことによりパイプラインが動いていないことに気づくことができずに、データの更新止まっていることを利用者が「はて?」と実際にデータ見ている中で検知したりすることが発生します。
つまり、正常じゃないけど、エラー通知が飛ばないというケースに対してモニタリングを行いたい時が発生するのです。
そんな時に役に立つのがdbtのプロセスとは別で動いてくれるDMFとアラートの仕組みです。
freshnessやrow_countなどを利用してデータの更新が停止していることを検知するように仕込めばdbtに依存しないモニタリングの冗長化が実現できます。
特殊なデータモニタリングの要件にも対応しやすい
他にもご利益が少しあるのでポエム的にまとめます。
個人的にはソースとして利用されているデータの更新が止まっていないかというのがクリティカルなので最も優先的にテストを設定する対象だと思っています。
一方で、世の中には土日祝日などのタイミングではほぼデータの更新が発生しないデータというのは存在します。そういった特殊なモデルの鮮度チェックは土日祝日では動いてほしくありません。
じゃあ、dbtをそもそも実行しなければいいのではないか?という話もあるかもしれませんが、ほぼ更新が発生しないだけで発生していたらデータとしては日次のバッチ処理の対象としたいというケースがあるかもしれません。つまりdbtは止められないということです。
(特にBtoB系は土日祝日にガッツリデータの更新が止まりがちだったりします。必ずしも毎回更新がないわけではないパターンもあったりするようなケースです。)
そういったケースでは、dbtでdata testをかなり作り込まないと偽陽性のエラー検知が発生してしまいオオカミ少年のようなモニタリングになってしまいがちです。
そんな場合でも柔軟に設定できるのがDMFなのです。
DMFはその仕組み上、モニタリング時の閾値の設計などはSQLベースでかなり柔軟に設定可能なので、土日祝日カレンダーなどを組み合わせて営業日かどうかの判定を組み込みやすいです。
(alertはtrue or falseで発火の条件を設定できますが、dbtのtestはエラー対象のレコードを返すように設計しないといけないので、ちょっと表現が複雑になってしまうケースがあります。ちょっとだけなので気にならない方は気にならないと思うレベルですが…)
鮮度以外でもメトリクスという形式で溜め込んでいるメリットはとても多くあります。
また、その日の断面だけでなくて、数日連続してある閾値を下回っていると通知をしたいなどの場合にはそもそもテーブルの設定を大きく変えないとモニタリングがうまくできないようなケースも出てきたりする場合もあります。DMFの場合はメトリクスとして過去の連続したデータを組み合わせてアラートのロジックを組めるのでとても柔軟性の高いモニタリングを後付けできます。
あと、dbtをbuildで動かしている場合はdata testが敏感すぎると後続のモデルのbuildがスキップされちゃうので偽陽性の出るテストは組みにくくて、結局じゃあテストに入れなくていいかみたいな妥協をすることもあるかもしれないです。更新されていないのが異常じゃないテーブルの扱いは永遠の課題です。
DMFじゃないとできないことは何一つないけど…
これにつきますが、DMFなんて無くても誰も困らない、そんな世の中なんだと思います。いい時代です。
そんな世の中だとしても私はDMFを推したい。なぜならサーバレスコンピューティングによる課金が平均的にならすとめちゃ安いからです。
(環境ごとに異なるので責任は取りませんが、小さめのテーブルでメタデータのクエリのみで完結するメトリクスの場合は平均でならすとXSの最小課金時間の60秒の10%以下くらい安くできる場合があります。元が大したことないのですが、チリつもです。)
ちなみに小話コーナー
DMFを色々検証している中で気になったことをつらつら書きます
freshnessにTIMESTAMP_NTZが入れられない件について
これはtimestampあるあるだと思うのですが、timestampのエイリアスがtimestamp_ntzだったりするので、何も考えずにぼーっとデータを取り込んでいるとtimestamp_ntzのまま取り込みがちですが、実際には結構多くのデータはtimestamp_ltzやtimestap_tzの方がよかったりします。(個人的には基本的にtimetamp_ltzで正しい時間になるように補正したりするのが直感的なのでわかりやすいと思っています。)
えっ!そもそも違いがわからないって!そんな人はドキュメントを読み込んでください!!!
(読んでもわからなかったら、SnowSightを開いて適当にそれぞれのデータ型での値を用意して = で比較するselect文を投げて、true/falseが完全に当てられるようになって下さい)timestamp_ntzはタイムゾーンの情報を持たないので実はAsia/Tokyoの時間と思っていたらUTCだったとか、その逆のパターンなどもあったりするかもしれません。つまり、timestamp_ntzはタイムゾーン問題を後回しにしている感があるデータ型だと思っています(個人の見解です)。
(ちゃんとタイムゾーンを把握した上であえてNTZを利用しているケースを否定するのはものではありません)
NTZを使うケースはそこそこあると思うのですが、ことfreshnessを利用する際にはタイムゾーンはクリティカルな影響を受けるのです。
なぜなら、freshnessはタイムスタンプの差分の秒数をメトリクスとして収集するのですが、その起点となるタイムスタンプはUTCではなくて実際のタイムゾーンになるからです。
もし取得対象のtimestampがAsia/Tokyoだったケースであればいいのですが、UTCだった場合にそのメトリクスは勝手に9時間ずれた状態になってしまいます。(と思うのですが、別にそこを考慮してアラームの閾値を調整すればいいだけなのでそこまでクリティカルかと言われるとそうでもないのです…)
つまり、DMFを利用してfreshnessを扱う時には基本的にローカルのタイムゾーンに合わせるべきという話です。(まぁ普通に揃えておくに越した事はないです。)
つまり、DMFを使いたいからきっちりとタイムゾーンを意識した設計を導入できるようになるわけです。TIMESTAMP_NTZでお茶を濁しているそこのあなた!これを機にちゃんとTIMESTAMPをタイムゾーンありの状態で扱えるようにしてみて下さい!
dbtでtableのmaterializationを利用して毎回create or replaceしているとせっかく設定したDMFも一緒に消える悲しみがある
dbtは便利ですが、materializedがtableとかviewだと毎回create or replaceが発生するという地味に痛い仕様があります。
replaceされるとせっかくDMF設定しても消えちゃうので、dbtのmacroを組んでyamlのconfigにmetaで設定を書いておいて、post_hookでそのマクロを呼び出して設定できるようにしておくといいと思います。
tableのIDが変わりますが、同じ名前なのでSQLでテーブル名で扱う分には問題なく扱えますのでモニタリングの面では問題ないです。
メタデータのみで完結するメトリクスを基本的には取得するべき
地味な話ですが、そこそこ複雑なjoinなどのロジックを含むviewだと単にrow_countを取ろうとしても毎回クエリを実行する必要があり、コストがすごくかかります。そしてそのコストはサーバレスの課金体系なので、ちょっとお高いです。
テーブルもしくは簡単な加工しかしていないでメタデータから情報を取得できるviewだけに適用するがDMFをコスパよく使うコツです。メタデータだけで済む場合は特にサーバーレスの課金体系のいいところだけ享受できて、XSの最小課金単位である1分よりもクレジットの消費が抑えられたりしました。
(もちろん、XSで1分丸々処理を詰め込めばwarehouseのクレジットの消費の方が低く抑えられたりする可能性もあります。ただ、そもそもDMFはサーバレスしか選択肢がないのであんまり深く考えても意味はないのですが)
あと異論は認めるのですが、個人的にはカスタムDMFは本当に必要に駆られた場合以外は作らない方がいいと思います。なぜならそのメトリクスの意味をちゃんと共通認識でいつまでも誰でもわかりやすく管理できますか?という問いに答えれれる人は少ないと思うからです。(私には無理だと思いました)
特に日次のレコードの増減などはwindow関数などを利用してメトリクスのテーブルから生成できたりするので無理にカスタムメトリクスを作らなくてもいいのです。メタデータのみで完結することが多いシステムDMFを組み合わせて利用するのがおすすめです。
最後に
個人的にはDMFって結構埋もれがちないい機能なのかもしれないと思っています。
ただ、なくてはならない存在でもないとも思います。
そんな君(DMF)にはこの言葉を捧げたいと思います。
土の中の水道管 高いビルの下の下水 大事なものは表に出ない。
by 相田みつを
昨今の煌びやかな"AI" Data Cloudじゃない方のSnowflakeの一面をフィーチャーしてみました。
実務は地味なところも多くありますが、そんなところにも寄り添ってくれるSnowflakeが好きです!
Discussion