为什么Python中获取PostgreSQL表比R慢这么多?

3

我需要对存储在PostgreSQL表中的数据进行一些统计处理。我一直在犹豫使用R还是Python。

如果使用R,我可以使用以下代码:

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

这是非常快的:仅需5秒即可获取包含约200,000行和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表格吗?


2
“dbGetQuery”与“execute”不是类似的吗?执行这一行时并没有提取结果吗? - Guybrush
这似乎是一个相当简单的psycopg2示例,执行它应该没有任何问题。如果执行此查询会导致整个计算机崩溃,那么我会开始怀疑您的python或psycopg2模块安装是否以某种方式损坏?fetchone()的行为如何? - match
@GuyBrush,使用dbSendQueryfetch来完成这种工作的方式。 - match
@Guybrush,我真的不理解你的评论。@match 我又尝试了一次使用 SQL 查询限制到20行。(这里是MySQL而不是PostgreSQL,但我认为这并不重要)。fetchall() 在20行的表格中工作得很好,但fetchone() 返回以下错误:mysql.connector.errors.InternalError: Unread result found - R. Bourgeon
1个回答

3
我虽然不是R专家,但很明显dbGetQuery()(实际上是:dbFetch())返回的是一种懒加载对象,不会将所有结果全部加载到内存中。否则,它会花费很长时间并占用所有内存。
对于Python/psycopg,绝对不要使用fetchall()来获取大型数据集,正确的解决方案是使用服务器端游标并进行迭代。
编辑-回答您在评论中的问题:

所以在执行fetchall()时选项cursor_factory=psycopg2.extras.DictCursor就可以解决问题了,对吗?

完全不是。正如我链接示例中写的那样,“解决问题”的方法是使用服务器端游标,在psycopg中通过命名游标来实现:

这里是重点,通过为游标指定名称,Psycopg2创建了一个服务器端游标,这样可以防止从服务器一次下载所有记录

cursor = conn.cursor('cursor_unique_name')

DictCursor是无关紧要的内容(在这个例子中不应该提到,因为它显然会让新手困惑)。

我有一个关于延迟对象概念(在R中返回的对象)的问题。如何将该对象作为数据框返回而不存储在我的RAM中?我觉得这有点神奇。

正如我所提到的,我对R及其实现一无所知,我推断出dbFetch返回的任何内容都是延迟对象,但拥有一个从外部源延迟获取值的对象并不神奇。Python的file对象是已知的例子:

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

在上面的代码段中,file对象f仅在需要时从磁盘获取数据。需要存储的仅是文件指针位置(以及最后读取的N个字节的缓冲区,但这是一些实现细节)。
如果您想了解更多,请阅读有关Python的可迭代对象(iterable)迭代器(iterator)的内容

当执行fetchall()时,选项cursor_factory=psycopg2.extras.DictCursor就可以解决问题了,对吧?这很奇怪,因为我以前在VBA中已经做过类似的事情,我100%确定当时我使用的是客户端游标。 - R. Bourgeon
我有一个关于惰性对象概念的小问题(在R中返回的那个)。如何将该对象作为数据框返回而不将其存储在我的RAM中?我觉得这有点神奇。 - R. Bourgeon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接