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