关于python:如何从sql查询创建大型pandas数据框而不会耗尽内存?

How to create a large pandas dataframe from an sql query without running out of memory?

我无法从我的MS SQL Server数据库查询一个超过500万条记录的表。我想能够选择所有的记录,但我的代码似乎失败时,选择大量的数据进入内存。

这工作:

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

…但这不起作用:

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

它返回此错误:

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

我在这里读到,从csv文件创建数据帧时存在类似的问题,解决方法是使用"迭代器"和"chunksize"参数,如下所示:

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

对于从SQL数据库查询,是否有类似的解决方案?如果没有,你最喜欢的工作是什么?我需要用其他方法成批地读取记录吗?我在这里读了一些关于在熊猫中使用大型数据集的讨论,但是执行select*查询似乎需要很多工作。当然有一个更简单的方法。


如注释所述,从pandas 0.15开始,在read_sql中有一个chunksize选项,用于按块读取和处理查询块:

1
2
3
sql ="SELECT * FROM My_Table"
for chunk in pd.read_sql_query(sql , engine, chunksize=5):
    print(chunk)

参考:http://pandas.pydata.org/pandas docs/version/0.15.2/io.html查询


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

您只需尝试分块读取输入表,然后从各个部分组装完整的数据帧,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
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)

也可能是整个数据帧太大,内存无法容纳,在这种情况下,除了限制要选择的行或列的数量之外,您没有其他选择。