❄️

streamlit in snowflake にて、 SQLが実行されないことがある

に公開

概要

Snowflake 上の Streamlit では、 Snowflake 上のテーブルに対して簡単にSQLを実行できます。

しかし先日、 SQLが実行出来たり出来なかったりするケースに遭遇しました。

原因や対処方法について記載します。

遭遇した問題の詳細

Snowflake 上の Streamlit にて、 Snowflake 上のテーブルに対して insert 文を実行する処理を実装しました。

from snowflake.snowpark.context import get_active_session
import streamlit as st

session = get_active_session()

if st.button('insert'):
  session.sql('insert into ...')

しかし、 テーブルを確認すると、行が増えていませんでした。

insert 文が失敗したのかと思い、結果を画面表示すると、成功しています。

...
if st.button('insert'):
  result = session.sql('insert into ...')
  st.write(result) # insert success count 1

そして、この状態では、該当テーブルに行が増えていました。

問題の原因

Snowpark Session の sql は、いわゆる 遅延実行 という振る舞いをします。

session.sql('some sql') だけではSQL文は実行されず、SQLの結果がプログラム上で参照されたときに、初めてSQLが実行されます。

...
if st.button('insert'):
  result = session.sql('insert into ...') # まだSQLは実行されない
  st.write(result) # SQLの結果を参照した、このタイミングでSQLが実行

イメージは、 Java Stream API の中間処理です。

Snowflake の公式ドキュメントにも、しっかり記載してありました。

You can use this method to execute a SQL query lazily, which means the SQL is not executed until methods like DataFrame.collect() or DataFrame.to_pandas() evaluate the DataFrame. For immediate execution, chain the call with the collect method: session.sql(query).collect().

SQL実行結果を参照したくない場合は、 collect() メソッドを実行すれば良いとのことです。

対処方法

以下のように修正します。

if st.button('insert'):
  session.sql('insert into ...').collect()

所感

遅延実行のおかげで、(条件分岐などで)参照されないデータは、そもそもSQLが実行されないようになり、余計な計算コストをかけずに済みます。

有難いと思う反面、ハマりポイントでもあるように感じました。

該当ドキュメントの検索は難しくなかったので、そこまで困ることは無いように思います。

本件とはズレますが、Snowflake のドキュメントは探しやすく、必要な情報も丁寧に書かれており、いつも助かっています。

参考文献

Discussion