こんにちは、id:masutaka26 です。
Looker を使い始めて 3 年目に突入しました。変わらず Feedmatic という広告運用コンサルティングのデータ整備をする毎日です。
今回はここ 1 年の懸案だった LookML Validation の堪え難い遅さを改善出来たので、共有します。
- 2 年間でコード量が肥大化した
- LookML Validation が堪え難いほど遅くなった
- My LookML Validator is slow!
- include を最適化したら半分弱の時間になった
- まとめ
- 余談
- 追記: LAMS を使って wildcard include を禁止する
2 年間でコード量が肥大化した
2 年前と比べて Feedmatic プロジェクトの .lkml
ファイルがものすごく増え、440 個、23,217 行1にもなりました。Explore は 62 個、テスト用も含めると 150 個もあります。相変わらずボッチ LookML 開発者ではあるのですが。💦
さて、Looker の JumpStart で教えて頂いた「モデル編成のベストプラクティス」のうちの 1 つにこちらがありました。
ユーザーが必要とする答えに簡単にアクセスできる、可能な限り少ない数の explore を使用する。
しかし、広告運用の文脈だと、クライアントごとに独自実装が必要なケースが多く、このコード量になってしまいました。💦
LookML Validation が堪え難いほど遅くなった
そんな LookML 開発に使用する Looker IDE には LookML Validator が付属しており、git commit 前に強制する設定をしています。
以前は一瞬で完了していましたが、最近は 20 秒以上かかります。ちょっとコメントを書き換えただけでこれだけ待たされるのは、なかなかの苦行です。
試作した別プロジェクト(41 ファイル、1999 行)はそんなにかからないため、単純にコード量に比例していると思いました。
念のため Looker のサポートに質問したところ、やはりコード量(プロジェクトのサイズ)が影響しているそう。そして Looker インスタンスの CPU やメモリ使用量に問題はないとのこと。
さらに、こちらの記事を紹介して頂きました。🙏
My LookML Validator is slow!
長い記事ではないので、ざっと翻訳します。
TL;DR
プロジェクトが大きければ大きいほど、検証には時間がかかります。
Quick wins
- 戦略的に "includes" する
- 常に他のすべてのビューをインクルードすることは開発上簡単かもしれないが、命名規則を使って必要なファイルだけを戦略的にインクルードすることで、パフォーマンスを向上させることができる
- 使用しない explore(および join、field など)をコメントアウトまたは削除する
- プロジェクトを複数のプロジェクトに分割することを検討する
LookML のベストプラクティスについては、こちらの記事をご覧ください。
Long answer
LookML のプロジェクトサイズ(総行数)と不要な include
の両方が LookML Validator の性能に影響を及ぼします。
Validation は 2 段階のプロセスで行われます。
1) 1 回目の検証では、プロジェクト内のすべてのファイルを読み込み、どこにも参照されていないファイルも含めて、メモリに読み込み、ソースコードを 1 モデルずつ完全に翻訳して、「コンパイル」エラーを探します。
2) 2 回目の検証は、各モデルで開始し、そのモデルから参照されるファイルのみを解析します。そして、そのモデルに基づいてクエリーを構築し、クエリーエラーや「実行時」エラーを探します。また、これらのパスは、すべての検証で行われることも重要です。
結論として、1 回目の検証は LookML プロジェクトのサイズに、2 回目の検証は不要な include
文に影響されます。したがって、LookML プロジェクトのサイズを適切に保つと同時に、より選択的かつ戦略的な include
を推奨するのが良いでしょう。
Bonus note
Explore ごとのフィールド数は、検証時間という点で非常に重要です。これはしばしばモデルのパースよりも時間がかかります。
include を最適化したら半分弱の時間になった
今回は「戦略的に "includes" する」をやってみました。
具体的には 56 個の .explore.lkml
ファイルを以下のように変更しました。ワイルドカード付きの include
を出来るだけ減らしました。
# 変更前 include: "/views/**/*.view" ↓ # 変更後 include: "/views/view1.view" include: "/views/view2.view" include: "/views/view3.view" include: "/views/view4.view" include: "/views/view5.view"
結果がこちら。たったこれだけで、20 秒かかっていた LookML validation が 12 秒弱にまで縮まりました。期待以上です!👏😂🎉
変更前(秒) | 変更後(秒) | |
---|---|---|
1 | 20.46 | 12.39 |
2 | 20.44 | 11.89 |
3 | 20.05 | 11.69 |
3 | 20.61 | 11.65 |
5 | 20.48 | 11.95 |
平均 | 20.41 | 11.91 |
ついでに、事情があって隠している Explore 10 個2の削除を確認してみたら、さらに速くなり、9 秒程度まで縮まりました。なるほど。
まとめ
ここ 1 年の懸案だった LookML Validation のパフォーマンスを改善しました。
include を最適化するだけで、ここまで速くなるとは驚きでした。おまけに LookML Validation のプロセスも理解することもできました。
💭 コンパイラ側で良しなにするのは難しいのかな、LAMS で警告してくれれば良いのかな。
引き続き、LookML 開発を妨げる課題があれば、解決していきます。💪
余談
Validate LookML
をクリックすると、すぐ Validate LookML
に戻ることがあるのですが、なんででしょう...?ファイル保存直後だとほぼ発生します。
Validation が終わる時間くらいまで待つと 2 回クリックしなくて良いみたいです。🙄
追記: LAMS を使って wildcard include を禁止する
LookML の Linter として LAMS というものがあります。
このカスタムルールを定義することで、今回のようなワイルドカード付きの include
を禁止することが出来ます。
manifest.lkml にこのように書くだけです。
# LAMS # rule: NO_WINC { # description: "Prohibit wildcard include to avoid increasing LookML verification time" # match: "$.files.*.include.*" # expr_rule: ($let file_path ($get ::project files ::path:2 $file_path)) # ($if ($match "\\*" ::match) # ($concat "Found wildcard include '" ::match "' in " ::file_path "") # true) ;; # }
Customizing LAMS にさらりと書いてありますが、指摘されたファイル名を出す方法が分からなかったので、Issue #95 で質問したら分かりました。これは分からない。💦