2009-01-17 38 views
15

我一直在使用python與RDBMS'(MySQL和PostgreSQL),我注意到我真的不明白如何使用遊標。Python的DB-API中的遊標如何工作?

通常情況下,一個有他的劇本通過客戶端DB-API連接到數據庫(如psycopg2或MySQLdb的):

connection = psycopg2.connect(host='otherhost', etc) 

然後一個創建一個光標:

cursor = connection.cursor() 

然後可以發出查詢和命令:

cursor.execute("SELECT * FROM etc") 

現在查詢的結果在哪裏,我想知道?它在服務器上嗎?或者我的客戶端上有一點,我的服務器上有一點?然後,如果我們需要訪問一些成果,我們取「時間:

rows = cursor.fetchone() 

rows = cursor.fetchmany() 

現在讓我們說,我不檢索所有的行,並決定執行另一個查詢,先前的結果會發生什麼?他們是一個開銷。另外,我應該爲每種形式的命令創建一個遊標,並以某種方式不斷地重複使用它作爲這些相同的命令;我頭psycopg2可以以某種方式優化多次執行但具有不同值的命令,如何以及是否值得?

THX

+1

Re:關於遊標的最佳實踐,來自FAQ(http://initd.org/psycopg/docs/faq.html):「我們的建議是幾乎總是創建一個新的遊標,並儘快處理舊遊標數據不再是必需的(對它們調用close())。唯一的例外是緊密循環,其中一個通常使用相同的遊標來處理大量的INSERT或UPDATE。 – 2013-06-13 12:15:35

回答

3

你,我知道這是個老:P

出現

DB-API的遊標被藍本SQL遊標之後。 AFA資源(行)管理而言,DB-API不指定客戶端是必須檢索所有行還是DECLARE實際SQL指針。只要fetchXXX接口能夠做到他們所期望的,DB-API就很高興。

AFA psycopg2遊標(正如您可能知道的那樣),「未命名的DB-API遊標」將獲取整個結果集 - AFAIK通過libpq緩衝在內存中。 「命名爲DB-API遊標」(psycopg2概念可能不可移植),將按需請求行(fetchXXX方法)。

正如「未知」所引用的,executemany可用於優化同一命令的多次運行。但是,它不適合需要準備好的陳述;當重複執行具有不同參數集的語句不是直接連續執行時,executemany()將執行與execute()一樣的操作。 DB-API爲驅動程序作者提供了緩存已執行語句的能力,但是它的實現(語句的範圍/生命期是什麼?)是未定義的,因此無法在DB-API實現中設置期望值。

如果您正在將大量數據加載到PostgreSQL中,我強烈建議您嘗試查找使用COPY的方法。

1

你使用PostgreSQL假設,光標可能只是使用該數據庫的本地遊標API來實現。您可能需要查看pg8000(純Python PostgreSQL DB-API模塊)的源代碼,以瞭解它如何處理遊標。你也可以看看the PostgreSQL documentation for cursors

1

當你在這裏看mysqldb documentation你可以看到他們實現了不同的遊標策略。所以一般的答案是:這取決於。

編輯:這是mysqldb API documentation。有一些信息如何每個遊標類型的行爲。標準光標將結果集存儲在客戶端中。所以我假設如果你沒有檢索所有的結果行會導致開銷,因爲即使你不提取的行也必須轉移到客戶端(可能通過網絡)。我的猜測是它與postgresql沒有什麼不同。

如果要優化用多個值重複調用的SQL語句,應查看cursor.executemany()。它準備一個SQL語句,以便它不需要每次調用它來解析:

cur.executemany('INSERT INTO mytable (col1, col2) VALUES (%s, %s)', 
       [('val1', 1), ('val2', 2)])