Pandas SQL chunksize

时间:2015-08-05 16:25:42

标签: python sql-server pandas chunks

这更像是一个关于理解而不是编程的问题。 我是Pandas和SQL的新手。我正在使用pandas从SQL读取一些特定的chunksize数据。 当我运行SQL查询时,例如 将pandas导入为pd

df = pd.read_sql_query('select name, birthdate from table1', chunksize = 1000)

我不明白的是,当我不给出一个chunksize时,数据存储在内存中我可以看到内存增长然而,当我给出一个chunksize时,内存使用率并不高。

我的意思是这个df现在包含了许多我可以作为

访问的数组
for df_array in df:
    print df.head(5)

我在这里不明白的是,SQL语句的整个结果是否保存在内存中,即df是一个携带多个数组的对象,或者它们是指向指向SQL查询创建的临时表的指针。

我很乐意对这个过程的实际运作方式有所了解。

3 个答案:

答案 0 :(得分:19)

让我们考虑两种选择,以及在两种情况下会发生什么:

  1. chunksize为None(默认值):
    • pandas将查询传递给数据库
    • 数据库执行查询
    • pandas检查并发现chunksize为None
    • pandas告诉数据库它希望立即接收结果表的所有行
    • 数据库返回结果表的所有行
    • pandas将结果表存储在内存中并将其包装到数据框中
    • 现在您可以使用数据框
  2. chunksize in not None:
    • pandas将查询传递给数据库
    • 数据库执行查询
    • pandas检查并发现chunksize有一些价值
    • pandas创建一个查询迭代器(通常'而True'循环,当数据库表示没有剩余数据时会中断)并在每次需要结果表的下一个块时迭代它
    • pandas告诉数据库它想要接收chunksize行
    • 数据库返回结果表中的下一个chunksize行
    • pandas将下一个chunksize行存储在内存中并将其包装到数据框中
    • 现在您可以使用数据框
  3. 有关详细信息,您可以看到pandas\io\sql.py模块,它有详细记录

答案 1 :(得分:17)

如果您未提供chunksize,则查询的完整结果会立即放入数据框中。

当您提供chunksize时,read_sql_query的返回值是多个数据帧的迭代器。这意味着你可以像这样迭代:

for df in result:
    print df

并且在每个步骤中df是一个数据帧(不是数组!),它保存查询的一部分数据。请参阅相关文档:http://pandas.pydata.org/pandas-docs/stable/io.html#querying

要回答有关内存的问题,您必须知道从数据库中检索数据有两个步骤:executefetch
首先执行查询(result = con.execute()),然后从该结果集中获取数据作为元组列表(data = result.fetch())。提取时,您可以指定一次要获取的行数。这就是当你提供chunksize时熊猫所做的事情 但是,许多数据库驱动程序已经在执行步骤中将所有数据放入内存,而不仅仅是在获取数据时。所以在这方面,记忆无关紧要。除了将数据复制到DataFrame之外,只有在使用chunksize进行迭代时才会在不同的步骤中进行。

答案 2 :(得分:2)

基本上,在有大量查询时,它可以阻止服务器内存不足。

输出为CSV

for chunk in pd.read_sql_query(sql , con, chunksize=10000):
    chunk.to_csv(os.path.join(tablename + ".csv"), mode='a',sep=',',encoding='utf-8')

或转到实木复合地板

count = 0
folder_path = 'path/to/output'

for chunk in pd.read_sql_query(sql , con, chunksize=10000):
    file_path = folder_path + '/part.%s.parquet' % (count)
    chunk.to_parquet(file_path, engine='pyarrow')
    count += 1