Psycopg2的fast_executemany替代

时间:2018-12-06 16:55:11

标签: python sqlalchemy

我有一个Redshift服务器,它是通过psycopg2初始化的(请注意,公司服务器上不支持ODBC,所以我不能使用pyodbc)。

当前,通过pd.to_sql()花费了10分钟的时间来处理30-35k行,该行从数据帧写入Redshift DB。因此,作为一种解决方法,我将DF作为csv下载,将文件推送到S3,然后使用copy写入数据库。

根据Speeding up pandas.DataFrame.to_sql with fast_executemany of pyODBCfast_executemany解决方案将是完美的-但是psycopg2不支持此解决方案。 我还根据https://github.com/d6t/d6tstack/blob/master/examples-sql.ipynb找到了d6tstack,但pd_to_psql不适用于Redshift,仅适用于Postgresql(不能copy... from stdin

我可以使用其他替代方法吗?

这是我的代码:

import sqlalchemy as sa

DATABASE = ""
USER = ""
PASSWORD = ""
HOST = "...us-east-1.redshift.amazonaws.com"
PORT = "5439"
SCHEMA = "public" 

server = "redshift+psycopg2://%s:%s@%s:%s/%s" % (USER,PASSWORD,HOST,str(PORT),DATABASE)
engine = sa.create_engine(server)
conn = engine.raw_connection()

with conn.cursor() as cur:
    cur.execute('truncate table_name')

df.to_sql('table_name', engine, index=False, if_exists='append') 

1 个答案:

答案 0 :(得分:4)

如果您无法使用COPY from S3并且必须依赖DML,则可以尝试将use_batch_mode=True传递给create_engine()

engine = create_engine('theurl', use_batch_mode=True)

在这台机器上,向Redshift集群简单地插入500行显示了启用批处理模式的合理改进:

In [31]: df = pd.DataFrame({'batchno': range(500)})

In [32]: %time df.to_sql('batch', engine, index=False, if_exists='append')
CPU times: user 87.8 ms, sys: 57.6 ms, total: 145 ms
Wall time: 1min 6s

In [33]: %time df.to_sql('batch', bm_engine, index=False, if_exists='append')
CPU times: user 10.3 ms, sys: 4.66 ms, total: 15 ms
Wall time: 9.96 s

请注意,熊猫0.20.2和0.24.0及更高版本将无法从使用批处理模式中受益,因为如果基础DBMS支持,则它们使用多值插入而不是executemany。使用多值插入应该会在吞吐量方面提供类似的改进,因为发出的查询更少。