python postgres我可以fetchall()100万行吗?

Med*_* Gh 18 python postgresql fetchall

我在python中使用psycopg2模块从postgres数据库中读取,我需要对列中的所有行进行一些操作,该行有超过100万行.

我想知道会cur.fetchall()失败或导致我的服务器出现故障?(因为我的RAM可能不会那么大,无法保存所有数据)

q="SELECT names from myTable;"
cur.execute(q)
rows=cur.fetchall()
for row in rows:
    doSomething(row)
Run Code Online (Sandbox Code Playgroud)

更聪明的方法是什么?

lin*_*nqu 28

Burhan指出的解决方案只通过获取单行来减少大型数据集的内存使用量:

row = cursor.fetchone()

但是,我注意到逐行获取行的速度明显减慢.我通过互联网连接访问外部数据库,这可能是它的原因.

拥有服务器端游标并获取一串行被证明是最高性能的解决方案.您可以更改sql语句(如alecxe答案),但也有使用psycopg2提供的功能的纯python方法:

cursor = conn.cursor('name_of_the_new_server_side_cursor')
cursor.execute(""" SELECT * FROM table LIMIT 1000000 """)

while True:
    rows = cursor.fetchmany(5000)
    if not rows:
        break

    for row in rows:
        # do something with row
        pass
Run Code Online (Sandbox Code Playgroud)

您可以在psycopg2 wiki中找到有关服务器端游标的更多信息

  • 你能定义“抓取”吗?因为查询仍然完全执行,所以数据存储在某处。在数据库上,仍然是单个查询,所以我不明白fetchone或fetchmany如何节省内存。 (2认同)
  • @StevenWade是个好问题,以这种方式执行操作不会减少数据库实例的内存消耗,没错。但是我理解这个问题是为了避免连接到数据库并获取数据的实例的内存消耗。 (2认同)

ale*_*cxe 24

考虑使用服务器端游标:

执行数据库查询时,Psycopg游标通常会获取后端返回的所有记录,并将它们传输到客户端进程.如果查询返回了大量数据,则客户端将分配大量内存.

如果数据集太大而无法在客户端实际处理,则可以创建服务器端游标.使用这种光标,可以仅向客户端传输受控数量的数据,从而可以检查大型数据集而无需将其完全保留在内存中.

这是一个例子:

cursor.execute("DECLARE super_cursor BINARY CURSOR FOR SELECT names FROM myTable")
while True:
    cursor.execute("FETCH 1000 FROM super_cursor")
    rows = cursor.fetchall()

    if not rows:
        break

    for row in rows:
        doSomething(row)
Run Code Online (Sandbox Code Playgroud)


Bur*_*lid 24

fetchall()获取arraysize最大限度,因此为了防止数据库受到大量攻击,您可以以可管理的批次获取行,或者只是单步执行游标直到其耗尽:

row = cur.fetchone()
while row:
   # do something with row
   row = cur.fetchone()
Run Code Online (Sandbox Code Playgroud)