Python+PYODBC+pandas导出大SQL表分块读取报错如何解决
报错原因
chunksize参数用法错误:当给pd.read_sql_query传入chunksize时,函数返回值不是单份数据集,而是由多个分块DataFrame组成的迭代生成器。你直接用pd.DataFrame(sql_query)包裹这个生成器,相当于把每个分块(本身是千行级的DataFrame)当成单行数据塞入新DataFrame,导致出现长度、形状不匹配的不规则嵌套序列,直接触发你看到的numpy弃用警告。- 逻辑违背分块读取的设计初衷:就算你把所有分块拼接成一个完整DataFrame再导出,本质还是把170万行数据全部载入内存,和不开
chunksize的效果完全一致,依然会触发内存上限报错。 - 格式选型不合理:Excel单工作表最大支持1048576行数据,170万行已经超出上限,就算导出成功也会丢失数据,且Excel写入内存占用远高于CSV格式,大表导出优先选CSV。
修正方案
- 优先导出为CSV格式:无行数限制,写入速度快、内存占用低,完全适配百万行级数据导出需求。如果必须导出Excel,需要按行数拆分到多个工作表存储,避免超上限丢数据。
- 采用「读一块、写一块」的流式逻辑:遍历分块生成器,内存中仅保留当前读取的单块数据,逐块追加写入文件,全程不会把全量数据载入内存。
- 写入时区分首次写入和追加写入:首次写入新建文件、写入表头,后续分块追加时跳过表头,避免重复写入列名。
可直接运行的修正代码(CSV版本,推荐)
import pyodbc import pandas as pd # 建立数据库连接 conn = pyodbc.connect( 'Driver={SQL Server};' 'Server=servername;' 'Database=DB01;' 'Trusted_Connection=yes;' ) export_path = r'C:\Users\user\Documents\BackupTest1.csv' chunksize = 10000 # 可根据机器内存调整,5000-20000都是合理值 first_chunk = True # 逐块读取、逐块写入 for chunk in pd.read_sql_query("select * from calltype", conn, chunksize=chunksize): # 统一转换类型、处理空值,彻底规避不规则序列警告 chunk = chunk.astype(object).where(pd.notnull(chunk), None) if first_chunk: chunk.to_csv(export_path, index=False, mode='w') first_chunk = False else: chunk.to_csv(export_path, index=False, mode='a', header=False) conn.close() print("Records Exported")
补充说明
如果确实需要导出为Excel格式,注意单sheet行数不能超过1048576,170万行需要拆分到至少2个sheet中。但Excel格式写入百万行数据耗时会是CSV的5-10倍,且内存占用更高,非必要不选择。
内容的提问来源于stack exchange,提问作者seanboyd_2
相关产品推荐
相关产品推荐

