Pandas调用to_sql向Redshift写入仅建表无数据导入问题求助
Pandas DataFrame导入Redshift无数据挂起问题解决方案
核心原因
- 当前使用普通PostgreSQL驱动连接Redshift,Pandas默认
to_sql生成逐行INSERT语句,Redshift作为分布式列式集群对单行/小批量INSERT性能极差,3万条数据也会出现长时间挂起甚至事务超时的情况 - DataFrame中
close_date、DateStamp字段为object类型,未转换为标准datetime格式,写入时可能触发Redshift隐式类型校验,阻塞事务 method='multi'参数对Redshift兼容性极差,Redshift不支持PostgreSQL多行INSERT语法的部分特性,反而会加剧事务阻塞
解决方案
方案1:使用COPY命令写入(官方推荐,效率最高)
该方案3万条数据可在数秒内完成写入,无需中转S3:
- 先安装Redshift专用驱动:
pip install sqlalchemy-redshift
- 执行写入的完整代码:
import pandas as pd from sqlalchemy import create_engine from io import StringIO # 转换日期字段格式,避免类型校验错误 df['close_date'] = pd.to_datetime(df['close_date']) df['DateStamp'] = pd.to_datetime(df['DateStamp']) # 初始化Redshift连接,使用专用驱动 conn = create_engine('redshift+psycopg2://UserName:Password@Database') # 将DataFrame写入内存缓冲区 buffer = StringIO() df.to_csv(buffer, index=False, header=False, sep='\t', na_rep='\\N') buffer.seek(0) # 调用Redshift COPY命令批量写入 raw_conn = conn.raw_connection() with raw_conn.cursor() as cur: cur.copy_expert( sql="COPY schema_name.table_name FROM STDIN WITH DELIMITER AS '\t' NULL AS '\\N'", file=buffer ) raw_conn.commit() raw_conn.close()
方案2:适配原有to_sql写法(仅适合1000行以内的极小批量数据)
如果必须使用to_sql接口,按以下要求修改代码即可:
- 提前转换所有日期类型字段为datetime格式
- 移除
method='multi'参数,Redshift不兼容该模式 - 连接串改用Redshift专用驱动前缀,不要使用普通PostgreSQL前缀
修改后代码参考:
import pandas as pd from sqlalchemy import create_engine # 转换日期字段格式 df['close_date'] = pd.to_datetime(df['close_date']) df['DateStamp'] = pd.to_datetime(df['DateStamp']) # 改用Redshift专用驱动 conn = create_engine('redshift+psycopg2://UserName:Password@Database') df.to_sql( 'table_name', con=conn, schema='schema_name', index=False, if_exists='append', chunksize=1000 )
内容的提问来源于stack exchange,提问作者Clannagh
相关产品推荐
相关产品推荐

