❄️

Julia から Snowflake に接続する

2020/12/18に公開

こんにちは、Snowflake でサポートエンジニアをやっている @indigo13love です。

現在、Julia 向けの Snowflake コネクタの用意はありませんが、PyCall パッケージ (PyCall.jl) を使用して Snowflake Connector for Python をインポートすることで接続することが可能です。

この記事では、どうやって Snowflake Connector for Python をインポートするか、そして実際に使ってみた様子をお見せします。

(本記事は所属する組織の公式見解ではなく、個人的なプラクティスの共有になります。)

Julia on Jupyter Notebook の環境を構築する

今回は Jupyter Notebook 上で検証していきます。

Julia のインストールと IJulia パッケージ (Jupyter への導入)は下記の記事を読めば完璧です。今回はビルドせずに Homebrew からさくっと入れます。

https://qiita.com/phigasui/items/8af41d1bcbe7ef276cfe

$ brew cask install julia
$ julia

] を入力して Pkg のモードに切り替え、add IJulia で IJulia をインストールして環境構築は完了です。

(@v1.5) pkg> add IJulia

これで Jupyter のプロセスを再起動すれば、Julia のノートブックが作成できるようになります。

Snowflake Connector for Python を導入する

まず前提となる PyCall パッケージを導入します。

Julia のインタプリタを起動して、再度 Pkg モードで PyCall を追加します。

(@v1.5) pkg> add PyCall

追加したら、バックスペースで Julia モードに戻れます。戻ったら using PyCall で PyCall パッケージをインポートし、pyimport_conda() 関数を使って Snowflake Connector for Python をインストールします。

julia> using PyCall

julia> pyimport_conda("snowflake.connector", "snowflake-connector-python", "conda-forge")

pyimport_conda() は Conda でパッケージをインストールするのですが、snowflake-connector-python パッケージは Anaconda Repository に登録されておらず、conda-forge リポジトリにのみ存在するので、第 3 引数に "conda-forge" を渡す必要があります。

https://anaconda.org/conda-forge/snowflake-connector-python

また、今回は DataFrame で結果を取得してみようと思うので、DataFrames パッケージと、Pandas DataFrame から Julia ネイティブの DataFrame に変換するために Pandas パッケージを入れておきます。

(@v1.5) pkg> add DataFrames
...
(@v1.5) pkg> add Pandas
...

実際に接続してみる

環境が整ったので実際に接続してみましょう。

サンプルノートブックは下記のリポジトリに置いてあります。

https://github.com/indigo13love/sample-notebook-snowflake-julia/blob/main/sample-notebook-snowflake-julia.ipynb

まず PyCall パッケージをインポートし、@pyimport で Snowflake Connector for Python をインポートします。

using PyCall
@pyimport snowflake.connector as snowflake

ここで注意点として、通常 Python から使う際には snowflake.connector としてインポートしますが、この . が Julia/PyCall では受け入れられないので、ここでは as を使って snowflake としてインポートします。

その後、Python で使うときと同じように、connect() で接続し、cursor() でカーソルオブジェクトを取得し、execute() でクエリを実行します。

今回は、以前の記事でも紹介した、デフォルトで共有されているサンプルデータベースの SNOWFLAKE_SAMPLE_DATA から TPC-H 用の小さめのデータセットを選んでクエリしてみます。

conn = snowflake.connect(
    user="",
    password = "",
    account="",
    warehouse="",
    database="",
    role="",
    schema=""
)
cur = conn.cursor()
pandas_df = cur.execute("select * from snowflake_sample_data.tpch_sf1.customer").fetch_pandas_all()

ここで fetch_pandas_all() を使うことにより、加工なしで Pandas DataFrame の形式で結果を取得することができます。

ただし、ここで pandas_df に格納されているオブジェクトは、PyObject 型、すなわち Python のオブジェクトで Julia ネイティブのオブジェクトではないため、取り回しが効きにくく、またパフォーマンスのメリットも得られない可能性が出てきます。

typeof(pandas_df)
PyObject

そこで、先ほど追加した Pandas パッケージを使用して、DataFrames パッケージで定義されている Julia ネイティブな DataFrame に変換していきます。

using DataFrames
using Pandas
df = DataFrames.DataFrame(Pandas.DataFrame(pandas_df))

なぜか 2 段階必要ですが、これがいちばんシンプルな方法のようです。

https://stackoverflow.com/questions/63731550/how-to-convert-a-python-pandas-into-a-julia-dataframe-using-pyjulia-and-back-t

これで Julia ネイティブな DataFrame として Snowflake から取得した結果を扱えるようになりました。

typeof(df)
DataFrames.DataFrame

まとめ

現状 Snowflake には Julia ネイティブのドライバ/コネクタは存在しませんが、このように、比較的シンプルな手順で Snowflake Connector for Python を使うことができます。

実際この記事を書くにあたっていろいろ検証しましたが、特につまずくポイントはありませんでした。(PyObject から DataFrame への変換がいちばん手こずった)

ぜひ Julia を使う際のデータベースとして Snowflake も候補に入れていただければと思います。

Discussion