■本記事の目的
Snowflakeに、構造化データで記載されたExcelファイルを直接テーブルにロードする検証を行うため。
SnowflakeのPythonワークシートにて、SnowPark、PandasなどのPythonライブラリによるプログラム検証を行うため。
■概要
Snowflake S3データロード:③外部ステージ から派生して検証する。
ストレージ統合、外部ステージはそのまま流用で、検証を行う。
今回は、単一のファイルをロードすることを行う。
■Pythonライブラリ
Pythonのコマンドは、以下をインストールします。
・snowpark
・pandas
・openpyxl
■検証テストデータ
Excel内のテストデータは、以下のようにA1セルから始まる構造化データの状態で、
xlsxの拡張子でS3に配置します。
※1行目はヘッダー
件数は、ヘッダー除きの17974件です。
■ストアドプロシージャ(Pythonプログラム)
ストアドプロシージャで定義します。※任意の名前で良いです。
ロードするテーブル名は、プログラム内で決定しておく必要があります。
ストアドプロシージャとテーブルの所属のデータベース・スキーマは同一である必要があります。
引数に、ファイルパスを設定しておきます。
このプログラムは、単一のファイルだけロードする仕様です。
CREATE OR REPLACE PROCEDURE import_excel_sp(file_path string)
RETURNS VARIANT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python', 'pandas', 'openpyxl')
HANDLER = 'main'
AS
$$
#ライブラリをインポートする。
from snowflake.snowpark.files import SnowflakeFile
from openpyxl import load_workbook
import pandas as pd
#ファイルパスURLからExcelファイルを展開する。
#Excelファイルデータをデータフレームに変換する。
#データフレームをテーブルにINSERTする。
def main(session, file_path):
with SnowflakeFile.open(file_path, 'rb') as f:
workbook = load_workbook(f)
sheet = workbook.active
data = sheet.values
# 最初の行をヘッダーとして設定
columns = next(data)[0:]
# 2行目以降のデータに基づいてDataFrameを作成する
df = pd.DataFrame(data, columns=columns)
df2 = session.create_dataframe(df)
#洗替の時は、mode("overwrite")に変更する。
df2.write.mode("append").save_as_table("<テーブル>")
return True
if __name__ == "__main__":
main()
$$;
■ストアドプロシージャを実行する。
実行する前にテーブルを0件にしておきます。
TRUNCATE TABLE <テーブル>;
0件確認
SELECT COUNT(*) FROM <テーブル>;
実行します。
build_scoped_file_url()関数は、外部ステージのパスからURLを生成します。
CALL IMPORT_EXCEL_SP(build_scoped_file_url(@<外部ステージ>, '/<フォルダ>/<ブック>.xlsx'));
■考慮点
CSVかつCOPY INTOでのロードと比べると、同じデータ内容でも10秒くらい差があると感じました。ウェアハウスのコスト・パフォーマンスを考えると、連続的な利用はあまり推奨はできない方法かもしれません。
■参考文献
今回のロード処理の参考で一番シンプルで分かりやすい参考でした。
https://medium.com/snowflake/simplify-data-ingestion-with-snowpark-python-file-access-f2bc0e4cd887
openpyxlで不明な構文があったための参考です。
https://www.soudegesu.com/en/post/python/pandas-with-openpyxl/
■あとがき
単一ファイルはロードできることは判明しました。
次回は、COPY INTOのように特定フォルダ内の複数ブックのエクセルファイルを一つのプログラムでロードできるか検証しようと考えています。