【问题标题】:Python Psycopg2 For Loop, Large Database IssuePython Psycopg2 For 循环,大型数据库问题
【发布时间】:2014-05-27 16:23:40
【问题描述】:

我正在尝试使用 psycopg2 和 python 遍历一个 8gb 的大型数据库。我已按照文档进行操作,但出现错误。我试图在不使用 .fetchall() 的情况下遍历数据库的每一行,因为它太大了,无法将其全部提取到内存中。您不能使用 fetchone(),因为它会单独获取每一列。

注意第一次通过会返回值,第二次通过会报错。

文档内容如下:

Note cursor objects are iterable, so, instead of calling explicitly fetchone() in a loop, the object itself can be used:
>>> cur.execute("SELECT * FROM test;")
>>> for record in cur:
...     print record
...
(1, 100, "abc'def")
(2, None, 'dada')
(3, 42, 'bar')

我的代码如下:

statement = ("select source_ip,dest_ip,bytes,datetime from IPS")
cursor.execute(statement)

for sip,dip,bytes,datetime in cursor:
    if sip in cidr:
        ip = sip
        in_bytes = bytes
        out_bytes = 0
        time = datetime
    else:
        ip = dip
        out_bytes = bytes
        in_bytes = 0
        time = datetime    
    cursor.execute("INSERT INTO presum (ip, in_bytes, out_bytes, datetime) VALUES (%s,%s,%s,%s);", (ip, in_bytes, out_bytes, time,))
    conn.commit()
    print "writing to presum"

我收到以下错误:

对于光标中的 sip、dip、字节、日期时间: psycopg2.ProgrammingError: 没有要获取的结果

【问题讨论】:

  • 你是如何创建光标的?此外,您可以同时将同一个光标用于两个不同的目的,为此使用第二个光标。
  • @jjanes cursor = conn.cursor() 它不会让我只用光标来做我必须使用 fetchall() 它会用光标提取前几个值,但它会说没有结果获取但显然有总和

标签: python postgresql psycopg2


【解决方案1】:

看起来您正在将一个元组传递给 cursor.execute。尝试传递您要运行的 sql 字符串。

statement = "select source_ip,dest_ip,bytes,datetime from IPS"
cursor.execute(statement)

【讨论】:

  • 好的,我这样做了,然后它通过了大约一半的测试数据,然后给了我要获取的结果,但是如果我使用 fetch all 它将遍历它们。
【解决方案2】:

您正在此处更改循环内的结果集

cursor.execute("INSERT INTO presum (ip, in_bytes, out_bytes, datetime) VALUES (%s,%s,%s,%s);", (ip, in_bytes, out_bytes, time,))

改为全部在 sql 中完成

statement = """
    insert into presum (ip, in_bytes, out_bytes, datetime)

    select source_ip, bytes, 0, datetime
    from IPS
    where source_ip << %(cidr)s

    union all

    select dest_ip, 0, bytes, datetime
    from IPS
    where not source_ip << %(cidr)s
"""

cidr = IP('200.90.230/23')

cursor.execute(statement, {'cidr': cidr.strNormal()})
conn.commit()

我假设 source_ip 的类型是 inet&lt;&lt; 运算符检查 inet 地址是否包含在子网中

【讨论】:

  • 您不能在 8gb 数据库上使用 fetch all,因为它无法将所有内容保存到内存中
  • @PythonDevOps 更好的方法
  • cidr 是一个 IPy 网络 cidr 范围。它被定义为一个全局变量。 cidr = IPy.IP('200.90.230/23') 我改变了数字,但你明白了
【解决方案3】:

我对这个问题很感兴趣。我想也许你可以做的是使用 cursor.fetchmany(size)。例如:

cursor.execute("select * from large_table")

# Set the max number of rows to fetch at each iteration
max_rows = 100
while 1:
  rows = cursor.fetchmany(max_rows)
  if len(rows) == 0:
     break
  else:
     for arow in rows:
        # do some processing of the row

也许这对你有用?

【讨论】:

    猜你喜欢
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    相关资源
    最近更新 更多