繁体   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