2017-01-03 19 views
2

我有400万行的表,我使用的psycopg2到execture一个:如何使用服务器端游标与psycopg2

SELECT * FROM ..WHERE query 

我没有服务器端光标听说过,我读了一当你期望获得很多结果时,这是一个好的做法

我找到的文档位有限,我有一些基本的问题。

首先我声明服务器端游标如:

cur = conn.cursor('cursor-name') 

然后我执行查询为:

cur.itersize = 10000 
sqlstr = "SELECT clmn1, clmn2 FROM public.table WHERE clmn1 LIKE 'At%'" 
cur.execute(sqlstr) 

我的问题是:我该怎么办?我如何得到结果?

难道我通过行迭代为:

row = cur.fetchone() 
while row: 
    row = cur.fetchone() 

或我使用支持fetchmany()和我这样做:

row = cur.fetchmany(10) 

但是在第二种情况下我怎么能“滚动”的结果?

还什么是itersize点?

回答

1

此外,以cur.fetchmany(n)你可以使用PostgreSQL cursors

cur.execute("declare foo cursor for select * from generate_series(1,1000000)") 
cur.execute("fetch forward 100 from foo") 
rows = cur.fetchall() 
# ... 
cur.execute("fetch forward 100 from foo") 
rows = cur.fetchall() 
# and so on 
+0

但我已经使用游标。你看过我的代码吗? – user1919

+0

@ user1919是的,我看到了。但服务器端游标在打开时速度更快。无论如何,你有另一种选择。试试两种方法:循环中的'fetchmany()'或上面提到的。 – Abelisto

+1

嗯。我懂了。但基于这个答案,我认为我已经使用服务器端游标:http://stackoverflow.com/questions/28343240/psycopg2-uses-up-memory-on-large-select-query – user1919

1

Psycopg2具有与服务器端游标工作一个漂亮的界面。这是一个可能的模板使用:

with psycopg2.connect(database_connection_string) as conn: 
    with conn.cursor(name='name_of_cursor') as cursor: 

     cursor.itersize = 20000 

     query = "SELECT * FROM ..." 
     cursor.execute(query) 

     for row in cursor: 
      # process row 

上面的代码创建了连接,并自动将查询结果放入一个服务器端游标。值itersize设置客户端一次从服务器端游标下拉的行数。您使用的值应该平衡网络调用的数量与客户端上的内存使用情况。例如,如果您的结果数为300万,则2000(默认值)的itersize值将导致1500次网络调用。如果2000行所消耗的内存很少,请增加该数量。

当使用for row in cursor时,您当然一次只能处理一行,但Psycopg2将一次为您预取itersize行。

如果你想使用fetchmany出于某种原因,你可以做这样的事情:

while True: 
    rows = cursor.fetchmany(100) 
    if len(rows) > 0: 
     for row in rows: 
      # process row 
    else: 
     break 

fetchmany这种用法不会引发网络调用服务器更多的行,直到预取批次已累。 (这是一个令人费解的例子,它提供了什么上面的代码,但演示了如何使用fetchmany应该有必要。)

相关问题