SnowflakeのStreamlitで、テーブルを取得するときのキャッシュの効果を確認する

Snowflakeからのデータの読み込みはst.cache_dataによるキャッシュを使うことで、ウィジェットの値変更時もスキャンと処理時間を節約できそうですね。
2024.01.22

データアナリティクス事業本部 機械学習チームの鈴木です。

SnowflakeのStreamlitでは、Snowparkでテーブルからデータを取得することができます。

データの取得を行う機能でキャッシュを利用し、Snowflakeのスキャン量を減らすことができるので確認しました。

この記事について

クイックスタートの 『Getting Started With Snowpark for Python and Streamlit』では、SnowparkでStreamlitからSnowflakeのテーブルを取得し、表示する例が紹介されています。

ここではst.cache_dataを使ったキャッシュが利用されています。

Streamlitではウィジェットの値が変わるたびにコードが再実行されるため、繰り返しのSnowflakeへのスキャンは気になるところなので、キャッシュを設定することにより本当にクエリがされないのかを確認してみました。

サンプルのコード

適当なコードですが、以下のようなものを準備しました。

# ライブラリの読み込み
from snowflake.snowpark.context import get_active_session
import streamlit as st

# ページの設定
st.set_page_config(layout="wide")

# 現在のセッションの取得
session = get_active_session()

# データの読み込み
@st.cache_data()
def load_data():
    snow_df = session.table("ML_HOL_DB_NSUZUKI.ML_HOL_SCHEMA.DIAMONDS")
    return snow_df.to_pandas()

# キャッシュデータの取得
snow_df = load_data()

# セレクトボックス
options = ["FAIR", "GOOD", "VERY GOOD", "PREMIUM", "IDEAL"]
option = st.selectbox('CUTを選択してください。', options)

# フィルタ結果の表示
def filter_head5_df(df, option):
    filter = df['CUT'] == option
    df_top_5 = df[filter].head(5)
    return df_top_5

st.dataframe(filter_head5_df(snow_df, option))

以前紹介したクイックスタートで作成していたDIAMONDSテーブルのうち、CUTの条件をセレクトボックスで選択し、該当するデータを5件表示するという内容になります。

特にハイライトした箇所で、テーブルのデータを読み込んでいますが、st.cache_dataでデコレートすることでキャッシュを設定しました。

クエリ結果の確認

キャッシュ設定があるとき

以下のようにアプリを実行しました。

キャッシュ設定あり-1

以下のように条件を変更しました。

キャッシュ設定あり-2

ActivityQuery Historyよりクエリ結果を見ると、1度だけクエリされていることが確認できました。

クエリ結果

キャッシュ設定がないとき

次に、以下のように@st.cache_data()をコメントアウトしてみて、アプリの表示内容とクエリ結果がどのようになるか確認しました。

# データの読み込み
# @st.cache_data()
def load_data():
    snow_df = session.table("ML_HOL_DB_NSUZUKI.ML_HOL_SCHEMA.DIAMONDS")
    return snow_df.to_pandas()

まず、FAIRの結果を表示した後、セレクトボックスでIDEALを選択しました。

クエリ結果を確認すると、以下のように2回SELECT文が実行されたことを確認できました。

クエリ結果(キャッシュなし)

セレクトボックスのように再実行が行われるコンポーネントを使う場合は、キャッシュ設定をしておかないとスキャンが毎回実行されてしまうため注意が必要ですね。

最後に

SnowflakeのStreamlitでst.cache_dataを使った際のキャッシュの挙動について、実際のクエリ履歴と比較して確認してみました。

参考になりましたら幸いです。