Lookerのキャッシュをきちんと理解する #looker

2021.08.24

Lookerではデータベースのパフォーマンスを維持するためにキャッシュポリシーを設定できます。

今回はLookerにおけるキャッシュの仕組みをおさらいします。

キャッシュって?

直近のデータを、すぐまた必要になったときにいちいち本来の場所まで取りに行かないでいいように、すぐに取り出せるところに置いておくことです。(ざっくり)

Lookerにおけるキャッシュ

Lookerではクエリが実行されたときにデータベースに直ぐに問い合わせるのではなく、まずはLooker内のキャッシュを確認して以前全く同じクエリが投げられていないかを確認します。

キャッシュにそのクエリがないことを確認して初めてLookerはデータベースにクエリを投げます。

キャッシュについて何も設定していない状態、つまり、デフォルトの状態でもLookerはキャッシュを1時間保持します。そのため、明示的にキャッシングポリシーを設定していなくても、クエリが実行されたらLookerはまずキャッシュを確認します。

キャッシングポリシーの設定

それでは、個別にキャッシュポリシーを設定する方法をご紹介します。

datagroupというパラメータでキャッシングポリシーを設定して、persist_forというパラメータでモデルやExploreにdatagroupで設定したキャッシングポリシーを適用します。

datagroupの設定

キャッシングポリシーを設定する単位は、モデル単位かExplore単位です。そのため、キャッシングポリシーを定義するdatagroupパラメータはモデルファイルに定義します。

# modelファイル
datagroup: datagroup_name {
  sql_trigger: SELECT MAX(id) FROM table;;
  max_cache_age: "24 hours"
}

datagroupパラメータには主に2つのサブパラメータを定義できます。2つのうちどちらかのサブパラメータを定義するだけでもきちんと動きますが、2つどちらも設定することを推奨しています。

sql_trigger

sql_triggerパラメータはdatagroupのサブパラメータのひとつです。

SELECT MAX(id) FROM tableのように1行1列を返すSQL文を定義します。

sql_triggerで設定したSQLを、Looker側で定期的にデータベースに対してクエリを投げて、返ってきた値が前回と変わっているかどうかを確認します。そして、値が前回を変わっていた場合、そのデータグループは引き金が引かれた状態(triggered state)となり、キャッシュに保存されているクエリ結果を無効化します。

下記公式ページでは、sql_triggerで使えるSQLの例が紹介されています。トリガーをテーブルの値ではなく、時間で指定する方法などが紹介されてるので参考にしてみてください。

また、sql_triggerで指定したSQLをデータベースに定期的に投げると説明しましたが、どれだけ頻繁に投げるかの設定はデータベースのコネクションの設定で行います。

詳しくはこちらの公式ドキュメントをご確認ください:PDTとデータグループのメンテナンススケジュール

max_cache_age

max_cache_ageパラメータは、datagroupのサブパラメータのもう一つです。

max_cache_age: 24 hoursのように"○秒"、"○分"、"○時間"と期間を定めて古いキャッシュが使われることを防ぎます。

sql_triggerの設定だけで足りる気がするかもしれませんが、もしもデータの更新があったのにsql_triggerの値が変わらなかった場合の保険として、max_cache_ageも併せて設定することを推奨しています。

persist_withの設定

設定したデータグループをモデルまたはExploreに適用させるのにpersist_withパラメータを設定します。

モデルとExploreの両方にデータグループを定義した場合、Exploreで定義されたデータグループが優先されます。

キャッシュを使用したくない場合

キャッシュを使用せずにクエリを実行したいことがあると思います。状況に合わせてキャッシュを使用せずに直接データベースへクエリを投げる方法をご紹介します。

Exploreまたはダッシュボード画面で

まずは、データグループでの設定を変更せずに、Exploreやダッシュボードの画面からキャッシュを利用せずにクエリを実行する方法をご紹介します。

Explore

Runボタン横のギアマークをクリックすると、Clear Cache & Refleshが表示されるので選択すると、キャッシュを利用せずに結果を出すことができます。

ちなみに、クエリ結果がデータベースに問い合わせた結果なのか、キャッシュからの結果なのかは、結果が返ってきた後のRunボタン横に表示されます。

データベースからの場合

上図の通り、500 rows・0.7s・just now 何行が何秒でたった今 といった表示の場合はデータベースに問い合わせた結果です。

キャッシュからの場合

上図の通り、500 rows・from cache・1m ago 何行がキャッシュから何分前に とキャッシュからと明示的に教えてくれます。

ダッシュボード

ダッシュボードもRun横のギアマークをクリックすると、Clear Cache & Refleshが表示されるので選択すると、キャッシュではなく再びデータベースへクエリを投げてくれます。

ダッシュボードの結果がデータベースに問い合わせた結果なのかどうかも、Run横の表示で確認することができます。しかし、Exploreとはちょっと勝手が異なります。

データベースからの場合

Run横にjust nowとのみ表示されます。

キャッシュからの場合

Exploreとは違ってnm agoと何分前にクエリが実行されたのかのみ表示されます。Runを押さなくても時間が経てばここの数字は自動で更新されました。(実際に目で確認するまで画面をじーっと見つめました。)

LookMLの設定で強制的にキャッシュを利用しないようにする

全クエリ毎回データベースへクエリを投げるためには、persist_forパラメータを以下の通り定義します。

# model
persist_for: "0 seconds"

# explore
explore: explore_name {
  persist_for: "0 seconds"
}

persist_forパラメータは、モデルやExploreのキャッシュの保持時間を設定するパラメータです。この設定を0秒にすることでキャッシュは0秒間保持されるということになるので、実行されたクエリは毎回データベースへ投げられるという仕組みです。

名前はデータグループを適用するpersist_withパラメータと似ていて、役割はmax_cache_ageパラメータと似ているという非常にややこしいパラメータです。

慣れてしまえば問題ないのですが、個人的には最初は、LookerIDEのサジェストを思いきり利用して、persist_forを選択すると文字列を入れる""(ダブルクォート)が入力されて、persist_withを選択するとダブルクォートが出てこないというので判断していました。

また、datagroupパラメータのサブパラメータにはpersist_forがないので、そもそもサジェストの選択を間違えることはないです。

まとめ

Lookerのキャッシュについてきちんと理解できたでしょうか?

何も設定していない状態でも1時間はキャッシュが効いてしまっているというのがミソと自分では思っています。

こちらのLookerのパフォーマンスを最適化するためのベストプラクティスを紹介する記事でも、ETLの処理に合わせてデータグループを設定して、最大限Lookerのキャッシュを利用することが推奨されています。

少なくとも初期モデルをユーザーにデプロイする際にはデータグループを設定しておくといいでしょう!