【发布时间】:2020-01-07 14:17:07
【问题描述】:
我们对 SQL Server 有很大的了解(大约有 5 亿条记录)。由于它不适合内存,我正在考虑使用 fetchmany 进行块处理,如下所示:
with pymssql.connect(host, user, pass, db) as conn:
query = f"SELECT * FROM view_name;"
with conn.cursor() as cursor, futures.ThreadPoolExecutor(3) as executor:
cursor.execute(query)
chunk_size = 5000
data = cursor.fetchmany(chunk_size)
while data:
future_rs = executor.submit(process_chunk, data)
data = cursor.fetchmany(chunk_size)
但是,看起来 cursor.execute 实际上会在我调用 fetchmany 之前尝试获取所有行,因为它非常慢。
我对文档的理解是cursor.execute 应该只准备查询而不是实现完整结果?
您将如何在可管理的时间内处理如此大的表格/视图?
PS:我也试过pyodbc,同样的问题。正如预期的那样,将查询更改为 select top 100 * from view_name 很快。
【问题讨论】:
-
您为什么要尝试将 5 亿行返回到您的应用程序?那是不可用的。如果这是一份工作,那么我预计它需要很长时间才能处理 5 亿行。但是 execute 方法会执行它所声明的操作,它会执行您传递给它的查询。
-
是的,返回 100 行所需的时间将少于 500,000,000...
execute表示执行,就像您认为的那样。您似乎“想要”在这里稍微改变一下单词的定义... -
查看this post 了解有关分页的一些想法。
-
这是一个批处理,而不是应用程序。我需要稍微处理一下这些数据并移动到不同的地方。我认为执行是懒惰的,因为有可用的 fetchall 和 fetchmeny 方法。如果完整的结果已经可用,我认为调用 fetchall 没有任何意义。它似乎只是将结果转换为列表。
-
我不能代表 pymssql,但 pyodbc 绝对不会获取
.execute上的所有行。使用默认事务隔离 (READ_COMMITTED) 的快速 Wireshark 测试显示——连接到 SQL Server:8_960 字节;执行“SELECT * FROM MillionRows”:82_310字节; fetchmany(5_000): 314_810 字节; fetchmany(995_000): 62_564_304 字节
标签: python sql-server performance pyodbc pymssql