Snowflake Connector for Python

abehsu
ㄚ北的所見所聞
6 min readJun 9, 2019

Prerequisites

  • Python ( 2.7.9(or higher) or 3.4.3(or higher) )

安裝以及測試connector

Install the connector

pipenv install snowflake-connector-python

Verify Your Installation

#Create validate.py

code

#執行validate.py
python validate.py

連線到Snowflake

方法一:透過帶參數的方式連線

python connect_normal.py <account> <region> <user> <role> <warehouse> <database> <schema>

方法二:透過Federated Authentication連線

如果你有使用SAML 2.0-compliant驗證功能,那你需要使用以下的做法

#sample
python connect_saml.py <account> <user> <role> <warehouse> <database> <schema>

方法三:利用 Key-Pair 認證方式

Snowflake提供使用Key-Pair的認證方式來取代傳統輸入帳號密碼的認證方式,Key-Pair認證方式需要RSA Key Pair,我們可以透過OpenSSL來產生

#unencrypted版本openssl genrsa -out rsa_key.pem 2048#encrypted版本(比較建議)openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8
# 透過產生好的私鑰產生公鑰
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
# 透過有更改權限的ROLE帳號進行ALTER USER的設置(只有SECURITY ADMIN或更高權限的ROLE可以做這個設定)
ALTER USER <username> SET RSA_PUBLIC_KEY='<public_key>'
# 查看更改後的設定,可以發現RSA_PUBLIC_KEY_FP設置成功
DESC USER <username>;
#Sample
python connect_keypair.py <account> <user> <role> <warehouse> <database> <schema>

Create a Warehouse, Database, Schema

注意事項:
如果想在Snowflake創建這類型的Objects,必須要擁有SYSADMIN的ROLE

Create Warehouse

Create Database

因為我們是使用CREATE DATABASE IF NOT EXISTS,所以當DB已經存在,我們在執行這支程式的時候,會發現他不會再創建一次DB也不會自動USING Database以及Schema

Create Schema

注意事項:
在Create Schema的時候,必須先指定好Database才能操作,如下圖
(snowflake.connector.errors.ProgrammingError: 090105 (22000): Cannot perform CREATE SCHEMA. This session does not have a current database. Call 'USE DATABASE', or use a qualified name.)
注意事項2:使用cursor().execute不支援Multiple SQL statementsError Message:
snowflake.connector.errors.ProgrammingError: 000006 (0A000): Multiple SQL statements in a single API call are not supported; use one API call per statement instead.
更改後

Using the Database, Schema and Warehouse

con.cursor().execute("USE WAREHOUSE SF_TUTS_WH")
con.cursor().execute("USE SCHEMA testdb_mg.testschema_mg")

Creating Tables and Inserting Data

LOADING DATA

除了使用Inset data的方式,你也可以將要Insert的檔案放在你的本機上,並且使用Bulk Load的方式將資料匯入Table中

將要Bulk Load的檔案放進目錄中(/tmp)

執行程式,利用 PUT & COPY將資料匯入

利用 List 查看 Table Stage

list @%test_table;

Querying Data

透過cursor來取得資料

方法ㄧ:傳統做法
方法二:使用比較方便的寫法
 方法三:如果只需要得到一筆單一結果,可以使用fetchone這個method
方法四:如果想要一次取得特定的筆數,可以使用fetchmany()
注意事項:如果return的結果,資料量太大記憶體無法負擔,可以使用fetchone()或是fetchmany()去慢慢處理方法五:如果想要一次拿到所有結果

對 Query 設定限定的 timeout

當你設定了timeout以後,只要Query超過設定的時間,就會有Error產生,同時整個過程會被rollback

使用 DictCursor 來獲取資料

如果你想依據Column來獲取資料,可以使用DictCursor來操作

Cancel Query by QueryId

藉由忽略型別轉換增加 Query 的 Performance

一般 Connector 預設會將會將 Snowflake 內部的datatype 轉成 Python的datatype,這樣將會增加一些Query的成本,可以看到下圖,BIBNUM這個欄位的型態被轉成python的Int,REPORTDATE被轉換成Python的datetime.datetime
如果開啟忽略轉型的設定後,可以發現所有的欄位都變被視為STRING,意思是在Application端拿到資料後,可以自己在進行轉換型別的動作

Binding Data

注意事項:Snowflake官網在這部分提到,不要用Python的formatting function,因為可能會有SQL Injection的風險

Using %(name)s as the placeholder

Using %s as the placeholder

Use a list object to bind data for the IN operator

Using ? as the placeholder (Bind data in the server side)

Using :N as the placeholder (Binding data in the server side)

Binding datetime with TIMESTAMP (Binding data in the server side)

注意事項:不像Client Side binding的方式,利用Sever Side binding的時候最好給定Snowflake 的 datatype,因為儘管現在大部分Python的data types都已經可以mapping到Snowflake的data types了,但是有少部分像python datetime 的datatype,可以對應到多種Snowflake的data types(像是:TIMESTAMPE_NTZ,TIMESTAMP_LTZ,TIMESTAMP_TZ),預設的話會對應到TIMESTAMP_NTZ

Retrieving Column Metadata

Column的metadata儲存在cursor物件裡面的description attribute中

Retrieving Query ID

平常我們可以透過Snowflake的Web UI ,進入到History的頁面去查詢每一個Query的Id, python 的 connector 也提供了一個Attribute來讓我們可以查詢

Error Handling

Using execute_stream to execucte SQL Script

利用 execute_stream的方式,就可以解決前面提到的,一次只能執行一個SQL Statement的問題,讓我們能同時執行多個SQL Statement

Using Context Manager to Connect and Control Transactions

Python 的 Connector 提供了 Context Manager 的功能,記得要將 Autocommit 的功能 disable 讓我們可以更靈活的根據statement的狀態來管理Transaction(commit or rollback)

Logging

注意事項:Logging的設定要在Application的最前面,才可以成功

注意事項

1.Snowflake connector將會使用一個暫時的資料夾作為儲存資料的目錄(不管是上傳PUT還是下載GET),這個檔案路徑可以設定在環境變數中(TMPDIR or TEMP or TMP),如果沒設定的話預設會在/tmp,所以在使用前要先確定這個暫時的資料夾檔案空間夠不夠用

Reference

疑問

  • DataBinding
  • 不懂”If paramstyle is specified as qmark or numeric in the connection parameter, the binding variables should be ? or :N, respectively, and the binding occurs in the server side.”這句的意思

這篇是依據Snowflake官網的教學,全部實作ㄧ次,並且將中間有些有錯誤或沒提到的地方做點補強,感謝大家看到最後,也希望如果有任何想法可以互相交流討論,感謝各位🙂

--

--

abehsu
ㄚ北的所見所聞

喜歡探索不同領域的人事物,喜歡將自己學習到的也分享給大家,並產生共同的討論,從中得到回饋。 Linkedln(https://www.linkedin.com/in/hsuyuming/)