[英]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的iteratable
和iterator
。
Python是解释器,意味着它逐行执行程序,这就是为什么在python中导入db的速度较慢。 要克服此问题,请使用cpython缓存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.