Python 大熊猫SQL块大小

Python 大熊猫SQL块大小,python,sql-server,pandas,chunks,Python,Sql Server,Pandas,Chunks,这与其说是编程问题,不如说是理解问题。 我对熊猫和SQL很陌生。我使用pandas从SQL中读取具有特定块大小的数据。 当我运行sql查询时,例如。 作为pd进口熊猫 df = pd.read_sql_query('select name, birthdate from table1', chunksize = 1000) 我不明白的是,当我没有给出chunksize时,数据存储在内存中,我可以看到内存在增长。然而,当我给出chunksize时,内存使用率并没有那么高 我得到的是,这个df现在

这与其说是编程问题,不如说是理解问题。 我对熊猫和SQL很陌生。我使用pandas从SQL中读取具有特定块大小的数据。 当我运行sql查询时,例如。 作为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查询创建的临时表的指针


我很高兴能对这一过程的实际情况有所了解。

让我们考虑两种选择,两种情况都会发生什么:

  • chunksize为无(默认值):
    • 将查询传递到数据库
    • 数据库执行查询
    • pandas检查并发现chunksize为None
    • pandas告诉数据库它希望一次接收结果表的所有行
    • 数据库返回结果表的所有行
    • pandas将结果表存储在内存中,并将其包装到数据帧中
    • 现在您可以使用数据帧了
  • chunksize(非无):
    • 将查询传递到数据库
    • 数据库执行查询
    • pandas检查并发现chunksize有一些值
    • pandas创建一个查询迭代器(通常是“while True”循环,当数据库说没有更多的数据留下时循环中断),并在每次需要结果表的下一个块时对其进行迭代
    • pandas告诉数据库它希望接收chunksize行
    • 数据库从结果表返回下一个chunksize行
    • pandas将下一个chunksize行存储在内存中,并将其包装到数据帧中
    • 现在您可以使用数据帧了

  • 要了解更多详细信息,您可以查看模块,它有很好的文档记录

    当您不提供
    chunksize
    时,查询的完整结果会立即放入数据帧中

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

    for df in result:
        print df
    
    在每个步骤中,
    df
    是一个数据帧(不是数组!),它保存查询的一部分数据。请参阅本页上的文档:

    要回答有关内存的问题,您必须知道从数据库检索数据有两个步骤:
    execute
    fetch

    首先执行查询(
    result=con.execute()
    ),然后将数据作为元组列表从该结果集中提取(
    data=result.fetch()
    )。提取时,可以指定要一次提取多少行。当您提供
    chunksize


    但是,许多数据库驱动程序已经在执行步骤中将所有数据放入内存,而不仅仅是在获取数据时。因此,在这方面,这对记忆应该没有多大影响。除了使用
    chunksize

    进行迭代时,将数据复制到数据帧中只需不同的步骤,这基本上是为了防止服务器在进行大规模查询时内存不足

    输出到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
    

    请注意,@joris的回答中提到,
    许多数据库驱动程序已经在执行步骤中将所有数据放入内存中
    。所以chunksize在很多情况下对内存使用没有多大帮助。