如何在不耗尽内存的情况下从 sql 查询创建大熊猫数据框?

新手上路,请多包涵

我无法从 MS SQL Server 数据库中查询超过 500 万条记录的表。我想选择所有记录,但是在将大量数据选择为内存中时,我的代码似乎失败了。

这有效:

 import pandas.io.sql as psql
sql = "SELECT TOP 1000000 * FROM MyTable"
data = psql.read_frame(sql, cnxn)

…但这不起作用:

 sql = "SELECT TOP 2000000 * FROM MyTable"
data = psql.read_frame(sql, cnxn)

它返回此错误:

 File "inference.pyx", line 931, in pandas.lib.to_object_array_tuples
(pandas\lib.c:42733) Memory Error

我在 这里 读到,从 csv 文件创建 dataframe 时存在类似的问题,解决方法是使用这样的“迭代器”和“块大小”参数:

 read_csv('exp4326.csv', iterator=True, chunksize=1000)

从 SQL 数据库中查询是否有类似的解决方案?如果没有,首选的解决方法是什么?我应该使用其他一些方法来分块读取记录吗?我 在这里 阅读了一些关于在 pandas 中处理大型数据集的讨论,但执行 SELECT * 查询似乎需要做很多工作。当然有更简单的方法。

原文由 slizb 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 628
2 个回答

更新:请务必查看下面的答案,因为 Pandas 现在内置了对分块加载的支持。

您可以简单地尝试逐块读取输入表,然后从各个部分组装完整的数据框,如下所示:

 import pandas as pd
import pandas.io.sql as psql
chunk_size = 10000
offset = 0
dfs = []
while True:
  sql = "SELECT * FROM MyTable limit %d offset %d order by ID" % (chunk_size,offset)
  dfs.append(psql.read_frame(sql, cnxn))
  offset += chunk_size
  if len(dfs[-1]) < chunk_size:
    break
full_df = pd.concat(dfs)

也有可能整个数据框太大而无法放入内存,在这种情况下,除了限制您选择的行数或列数外,您别无选择。

原文由 ThePhysicist 发布,翻译遵循 CC BY-SA 3.0 许可协议

chunksize 仍然会加载内存中的所有数据, stream_results=True 就是答案。它是服务器端游标,可以加载给定块中的行并节省内存.. 在许多管道中有效使用,当您加载历史数据时它也可能会有所帮助

stream_conn = engine.connect().execution_options(stream_results=True)

将 pd.read_sql 与块大小一起使用

pd.read_sql("SELECT * FROM SOURCE", stream_conn , chunksize=5000)

原文由 Owais Ajaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题