Pythonのデータフレームがあります。このデータを新しいテーブルとしてRedshiftに書き込むことはできますか? Redshiftへのdb接続を正常に作成し、簡単なsqlクエリを実行できます。次に、データフレームを書き込む必要があります。
to_sql
を使用して、データをRedshiftデータベースにプッシュできます。 SQLAlchemyエンジンを介したデータベースへの接続を使用してこれを行うことができました。 index = False
呼び出しでto_sql
を設定してください。テーブルが存在しない場合は作成されます。テーブルを置き換えるか、テーブルに追加するか、テーブルが既に存在する場合は失敗するかを指定できます。
from sqlalchemy import create_engine
import pandas as pd
conn = create_engine('postgresql://username:[email protected]:5439/yourdatabase')
df = pd.DataFrame([{'A': 'foo', 'B': 'green', 'C': 11},{'A':'bar', 'B':'blue', 'C': 20}])
df.to_sql('your_table', conn, index=False, if_exists='replace')
SQLAlchemyを介してRedshiftに接続するには、 pip install psycopg2
が必要になる場合があることに注意してください。
import pandas_redshift as pr
pr.connect_to_redshift(dbname = <dbname>,
Host = <Host>,
port = <port>,
user = <user>,
password = <password>)
pr.connect_to_s3(aws_access_key_id = <aws_access_key_id>,
aws_secret_access_key = <aws_secret_access_key>,
bucket = <bucket>,
subdirectory = <subdirectory>)
# Write the DataFrame to S3 and then to redshift
pr.pandas_to_redshift(data_frame = data_frame,
redshift_table_name = 'gawronski.nba_shots_log')
S3にアクセスできると仮定すると、このアプローチは機能するはずです。
ステップ1:DataFrameをcsvとしてS3に書き込みます(これにはAWS SDK boto3を使用します)
ステップ2:DataFrameからRedshiftテーブルの列、データ型、キー/インデックスを知っているので、create table
スクリプトを生成し、Redshiftにプッシュして空を作成できるはずです。表
ステップ3:Python環境からRedshiftにcopy
コマンドを送信して、ステップ3で作成した空のテーブルにデータをコピーします
常に魅力のように機能します。
ステップ4:クラウドストレージの人々が大声で叫ぶ前に、S3からcsvを削除します
これを数回繰り返している場合、関数内の4つのステップすべてをラップすることで整頓されます。
pandas df.to_sql()
を使用しようとしましたが、非常に遅くなりました。50行を挿入するのに10分以上かかりました。 this 未解決の問題を参照してください。 (執筆時点)
ブレイズエコシステムから odo
を使用してみました(問題の議論の推奨事項に従って)が、ProgrammingError
に直面しましたが、調査する必要はありませんでした。
最後に働いたもの:
import psycopg2
# Fill in the blanks for the conn object
conn = psycopg2.connect(user = 'user',
password = 'password',
Host = 'Host',
dbname = 'db',
port = 666)
cursor = conn.cursor()
args_str = b','.join(cursor.mogrify("(%s,%s,...)", x) for x in Tuple(map(Tuple,np_data)))
cursor.execute("insert into table (a,b,...) VALUES "+args_str.decode("utf-8"))
cursor.close()
conn.commit()
conn.close()
うん、普通の古いpsycopg2
。これはnumpy配列用ですが、df
からndarray
への変換はそれほど難しくないはずです。これにより、約3k行/分が得られました。
ただし、他のチームメイトからの推奨事項による最速のソリューションは、データフレームをTSV/CSVとしてS3クラスターにダンプしてからコピーした後にCOPYコマンドを使用することです。本当に巨大なデータセットをコピーする場合は、これを調査する必要があります。 (試してみると、ここで更新します)
以前はpandas to_sql()
関数に依存していましたが、速度が遅すぎます。最近、次のことに切り替えました。
_import pandas as pd
import s3fs # great module which allows you to read/write to s3 easily
import sqlalchemy
df = pd.DataFrame([{'A': 'foo', 'B': 'green', 'C': 11},{'A':'bar', 'B':'blue', 'C': 20}])
s3 = s3fs.S3FileSystem(anon=False)
filename = 'my_s3_bucket_name/file.csv'
with s3.open(filename, 'w') as f:
df.to_csv(f, index=False, header=False)
con = sqlalchemy.create_engine('postgresql://username:[email protected]:5439/yourdatabase')
# make sure the schema for mytable exists
# if you need to delete the table but not the schema leave DELETE mytable
# if you want to only append, I think just removing the DELETE mytable would work
con.execute("""
DELETE mytable;
COPY mytable
from 's3://%s'
iam_role 'arn:aws:iam::xxxx:role/role_name'
csv;""" % filename)
_
ロールはS3へのredshiftアクセスを許可する必要があります。詳細については、 here を参照してください
300KBファイル(12000x2データフレーム)の場合、pandas to_sql()
functionで取得していた8分に比べて4秒かかります。
この会話のためにPostgres = RedShift 2つのオプションがあります:
オプション1:
パンダから: http://pandas.pydata.org/pandas-docs/stable/io.html#io-sql
Pandas.io.sqlモジュールは、データ取得を容易にし、DB固有のAPIへの依存を減らすためのクエリラッパーのコレクションを提供します。データベースの抽象化は、SQLAlchemyがインストールされている場合に提供されます。さらに、データベース用のドライバーライブラリが必要になります。そのようなドライバーの例は、PostgreSQLの場合はpsycopg2、MySQLの場合はpymysqlです。
データフレームの作成
次のデータがDataFrameデータにあると仮定すると、to_sql()を使用してデータベースに挿入できます。
id Date Col_1 Col_2 Col_3
26 2012-10-18 X 25.7 True
42 2012-10-19 Y -12.4 False
63 2012-10-20 Z 5.73 True
In [437]: data.to_sql('data', engine)
一部のデータベースでは、大きなDataFrameを書き込むと、パケットサイズの制限を超えているためエラーが発生する可能性があります。これは、to_sqlを呼び出すときにchunksizeパラメーターを設定することで回避できます。たとえば、次の例では、一度に1000行のバッチでデータベースにデータを書き込みます。
In [438]: data.to_sql('data_chunked', engine, chunksize=1000)
オプション2
または、dataと呼ばれるデータフレームがある場合、単純にiterrowsを使用してループします:
for row in data.iterrows():
次に、各行をデータベースに追加します。行ごとに挿入する代わりにコピーを使用します。これははるかに高速になるためです。
http://initd.org/psycopg/docs/usage.html#using-copy-to-and-copy-from