簡體   English   中英

為什么在Python中獲取postgreSQL表比在R中慢得多?

[英]Why is fetching a postgreSQL table so much slower in Python than in R?

我必須對存儲在PostgreSQL表中的數據進行一些統計處理。 我一直在使用R和Python之間猶豫。

對於RI,請使用以下代碼:

require("RPostgreSQL")
(...) #connection to the database, etc
my_table <- dbGetQuery(con, "SELECT * FROM some_table;")

這是非常快的:只需要5秒鍾就可以獲取一個表,該表包含約20萬行和15列,並且幾乎沒有NULL。

對於Python,我使用以下代碼:

import psycopg2  
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
cursor.execute("SELECT * FROM some_table;")
my_table = cursor.fetchall()

令人驚訝的是,這導致我的Python會話死機並且計算機崩潰。

當我將這些庫用作“黑匣子”時,我不明白為什么R中這么快的東西在Python中可能會這么慢(因此幾乎不可能實際使用)。

有人可以解釋這種性能差異,也可以告訴人們是否存在一種更有效的方法來獲取Python中的pgSQL表嗎?

我不是R方面的專家,但是很顯然dbGetQuery() (實際上是: dbFetch() )返回的是一個惰性對象,不會將所有結果都加載到內存中-否則當然會花費很多時間,而且還會占用您的所有內存。

wrt / Python / psycopg,您一定不要想要fetchall()一個巨大的數據集。 正確的解決方案是使用服務器端游標並對其進行迭代。

編輯-回答您評論中的問題:

所以執行fetchall()時,使用cursor_factory = psycopg2.extras.DictCursor選項可以解決問題,對嗎?

一點也不。 正如我喜歡的示例中的所有字母所寫,“成功的訣竅”是使用服務器端游標,這是通過命名游標來完成的(在psycopg中):

這里是重要的部分, 通過為游標指定名稱psycopg2創建了服務器端游標,該游標阻止了從服務器一次下載所有記錄

cursor = conn.cursor('cursor_unique_name')

DictCursor東西實際上是無關緊要的(在此示例中不應提及,因為它顯然會使新來者感到困惑)。

關於惰性對象(R中返回的那個)的概念,我還有一個疑問。 如何將對象作為數據幀返回而不將其存儲在我的RAM中? 我覺得這有點神奇。

正如我提到的那樣,我並不熱衷於R及其實現-我推斷dbFetch返回的任何dbFetch都是您描述的行為中的一個惰性對象-但是,擁有一個可以從外部源懶惰地獲取值的對象並沒有什么神奇之處。 Python的file對象是一個已知的示例:

with open("/some/huge/file.txt") as f:
    for line in f:
        print line

在以上代碼段中, file對象f僅在需要時才從磁盤獲取數據。 所有需要存儲的就是文件指針位置(以及從磁盤讀取的最后N個字節的緩沖區,但這是實現的細節)。

如果您想了解更多信息,請閱讀Python的iteratableiterator

Python是解釋器,意味着它逐行執行程序,這就是為什么在python中導入db的速度較慢。 要克服此問題,請使用cpython緩存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM