【问题标题】:Is PyMySQL's fetchone() buffered?PyMySQL 的 fetchone() 是否缓冲?
【发布时间】:2021-03-31 07:49:09
【问题描述】:

我正在执行可能导致数千行的数据库查询。

最简单的方法是遍历fetchall()

import pymysql

sql_command = "SELECT * FROM table WHERE some_condition;"
connection = pymysql.connect(...)
cursor = connection.cursor()
nof_affected_rows = cursor.execute(sql_command)
for row in cursor.fetchall():
    # process row

但是,我担心这里的内存耗尽。因此,另一种天真的方法是迭代 fetchone,一次一个元素。

import pymysql

sql_command = "SELECT * FROM table WHERE some_condition;"
connection = pymysql.connect(...)
cursor = connection.cursor()
nof_affected_rows = cursor.execute(sql_command)
while True:
    row = cursor.fetchone()
    if not row:
        break
    # process row

现在一位同事认为我应该使用fetchmany(),因为它会一次检索多个元素,从而避免往返。同时我会控制内存消耗。

这是真的吗? fetchone() 是否缓冲。如果是缓冲的,扩展到哪个范围?

【问题讨论】:

    标签: pymysql


    【解决方案1】:

    PyMySQL 在执行查询时会急切地下载所有元素。

    很遗憾,我无法在文档中找到明确的陈述。所以我做了一个小实验。

    我启动了IPython并执行了以下代码sn-p:

    import pymysql
    
    sql_command = "SELECT * FROM table WHERE some_condition;"
    connection = pymysql.connect(...)
    cursor = connection.cursor()
    nof_affected_rows = cursor.execute(sql_command)
    

    这导致了大约。要加载 450000 行。

    在一个单独的终端中,我使用htop 监控了 IPython 的内存消耗。内存消耗从 0.1% 上升到 7.3%,相当于大约 7.3%。 2.2GiB 内存。

    我断开网络后,我仍然能够从光标中检索所有元素。

    因此我得出结论,所有行都在cursor.execute() 处检索。因此,在 PyMySQL 中是否使用fetchonefetchmanyfetchall 的问题归结为更方便的问题。

    【讨论】:

      【解决方案2】:

      您可以使用SSCursor

      cursor = connection.cursor(pymysql.cursors.SSCursor)
      cursor.execute(sql_command)
      for row in cursor:  # Cursor is iterable. You don't have to call `fetch*()` methods.
          # process row
      

      【讨论】:

        猜你喜欢
        • 2021-01-17
        • 2015-11-17
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 2013-11-03
        • 1970-01-01
        • 2015-02-11
        相关资源
        最近更新 更多