2017-01-03 55 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應該有必要。)