[英]Python psycopg2 cursors
從psycopg2文檔中:
執行數據庫查詢時,Psycopg游標通常會獲取后端返回的所有記錄,並將它們轉移到客戶端進程。 如果查詢返回了大量數據,則客戶端將按比例分配大量內存。 如果數據集太大而無法在客戶端實際處理,則可以創建服務器端游標。
我想查詢一個可能包含數千行的表,並對每個表執行一些操作。 普通游標會真正將整個數據集帶到客戶端嗎? 聽起來不太合理。 該代碼類似於以下內容:
conn = psycopg2.connect(url)
cursor = conn.cursor()
cursor.execute(sql)
for row in cursor:
do some stuff
cursor.close()
我希望這是一個流操作。 第二個問題是關於游標的范圍。 在我的循環中,我想更新另一個表。 我是否需要打開一個新的光標並每次都關閉? 每個項目更新都應在自己的事務中,因為我可能需要回滾。
for row in cursor:
anotherCursor = anotherConn.cursor()
anotherCursor.execute(update)
if somecondition:
anotherConn.commit()
else:
anotherConn.rollback
cursor.close()
========編輯:我對第一部分的回答========
好的,我將嘗試回答問題的第一部分。 普通游標實際上會在您調用execute之后立即帶走整個數據集,甚至開始迭代結果集之前。 您可以通過在每個步驟檢查進程的內存占用量來進行驗證。 但是實際上需要服務器端游標是由於Postgres服務器而不是客戶端,並且在此處進行了說明: http : //www.postgresql.org/docs/9.3/static/sql-declare.html
現在,這在文檔中還不是很明顯,但是實際上可以在事務期間臨時創建此類游標。 無需使用特定的SLQ語句等顯式創建返回數據庫中的refcursor的函數。使用psycopg2,您僅需在獲取游標時給出名稱,便會為該事務創建一個臨時游標。 所以代替:
cursor = conn.cursor()
您只需要:
cursor = conn.cursor('mycursor')
就是這樣,它起作用了。 我假設在使用JDBC和設置fetchSize的情況下,相同的操作都是在后台進行的。 它只是更加透明。 在此處查看文檔: https : //jdbc.postgresql.org/documentation/head/query.html#query-with-cursor
您可以通過查詢同一事務內的pg_cursors視圖來測試此方法是否有效。 獲取客戶端游標后,服務器端游標出現,而關閉客戶端游標后,服務器端游標消失。 因此,最重要的是:我很高興對我的代碼進行更改,但是我必須說,對於那些沒有使用postgres的人來說,這是一個很大的難題。
實際上,您已經回答了問題;)。
從文檔:
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
BEGIN
OPEN $1 FOR SELECT col FROM test;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
並在代碼中:
cur1 = conn.cursor()
cur1.callproc('reffunc', ['curname'])
cur2 = conn.cursor('curname')
for record in cur2: # or cur2.fetchone, fetchmany...
# do something with record
pass
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.