You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何pandas.read_sql执行相同SQL查询的速度远慢于SSMS?

可能的原因

  • 数据类型转换开销:SSMS仅需将查询结果渲染为文本展示,不需要做额外的类型映射;但pandas.read_sql需要将SQL Server返回的每一列数据转换为pandas/numpy对应的兼容类型,若结果集中包含大量字符串、日期、高精度decimal类型字段,转换开销会被放大,这是最常见的性能差异来源。
  • 结果集拉取逻辑差异:你在SSMS中看到的1秒通常是首屏结果加载完成的时间,SSMS默认采用流式分页加载,不需要等全量结果返回就可以展示;但pandas.read_sql默认会将整个结果集全部拉取到本地、完成转换生成完整DataFrame后才会返回,你统计的时长包含了全量数据拉取+类型转换的总开销。
  • 驱动拉取批次配置不合理:你使用的数据库驱动(如pyodbc、pymssql)默认的批量拉取行数(arraysize)通常很小,每次仅从服务端拉取数百行数据,频繁的网络往返会大幅增加总耗时;而SSMS默认使用大批次拉取策略,网络开销更低。
  • 会话参数不同导致执行计划差异:SSMS和Python数据库驱动的默认会话配置(如ANSI_NULLS、ARITHABORT等SET参数)可能存在差异,即便查询语句完全相同,SQL Server也可能生成效率差异极大的执行计划,导致查询本身的执行耗时就不同。
  • 内存分配开销:pandas DataFrame的内存存储格式相比数据库返回的原始二进制结果开销更大,若结果集行数达到十万级以上,内存分配、数据拷贝的开销也会占总耗时的一定比例。

优化方案

  • 调整驱动批量拉取配置,以pyodbc为例,执行查询前先设置游标批次大小:
queryExecStart = time.time()
# 调整批量拉取行数,可根据实际结果集大小调整到10000~100000区间
self.conn.cursor().arraysize = 50000
sqlDataFrame = pandas.read_sql(query, self.conn)
self.logging(level="info", msg=f"Pandas data read duration {round(time.time() - queryExecStart, 3)} sec. Query: {queryName}")
  • 避免使用SELECT *,仅查询业务需要的字段,减少需要转换和传输的数据量。
  • 若结果集极大,可通过chunksize参数分批拉取处理,避免一次性加载全量数据到内存:
for chunk in pd.read_sql(query, self.conn, chunksize=10000):
    # 分批处理每块数据
    process_chunk(chunk)
  • 可替换为性能更高的驱动如turbodbc,其针对批量数据传输做了专门优化,相比默认pyodbc读取速度可提升数倍。

内容的提问来源于stack exchange,提问作者Melih Kocaadam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 15:45:03