游标如何在Python DB-API中工作?

时间:2009-01-17 23:58:21

标签: python performance rdbms cursors psycopg2

我一直在使用python和RDBMS'(MySQL和PostgreSQL),我注意到我真的不明白如何使用游标。

通常,他的脚本通过客户端DB-API(如psycopg2或MySQLdb)连接到数据库:

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

然后创建一个光标:

cursor = connection.cursor()

然后可以发出查询和命令:

cursor.execute("SELECT * FROM etc")

现在查询的结果在哪里,我想知道?它在服务器上?还是我的客户端上的一点点,我的服务器上的一点点?然后,如果我们需要访问某些结果,我们会获取'em:

rows = cursor.fetchone() 

rows = cursor.fetchmany()

现在假设,我没有检索所有行,并决定执行另一个查询,以前的结果会发生什么?是他们的开销。

另外,我应该为每种形式的命令创建一个游标,并以某种方式不断地将它重用于那些相同的命令;我头psycopg2可以某种方式优化多次执行但具有不同值的命令,如何以及它是否值得?

THX

3 个答案:

答案 0 :(得分:7)

是的,我知道已经好几个月了:P

在SQL游标之后,DB-API的光标似乎是紧密建模的。关注AFA资源(行)管理, DB-API不指定客户端是否必须检索所有行或DECLARE实际SQL游标。只要fetchXXX接口做了他们应该做的事情,DB-API就很高兴。

AFA psycopg2游标(您可能知道),“未命名的DB-API游标”将获取整个结果集 - 由libpq在内存中缓冲的AFAIK。 “命名的DB-API游标”(一种可能不可移植的psycopg2概念)将按需请求行(fetchXXX方法)。

正如“unbeknown”所引用的那样,executemany可用于优化同一命令的多次运行。但是,它不适用于准备好的陈述的需要;当重复执行具有不同参数集的语句不是直接顺序时,executemany()将执行与execute()一样好的操作。 DB-API确实“提供”驱动程序作者能够缓存已执行的语句,但是它的实现(语句的范围/生命周期是什么?)是未定义的,因此不可能在DB-API实现中设置期望。

如果要将大量数据加载到PostgreSQL中,我强烈建议您尝试使用COPY。

答案 1 :(得分:2)

假设你正在使用PostgreSQL,游标可能只是使用数据库的本机游标API实现的。您可能需要查看pg8000(纯Python PostgreSQL DB-API模块)的源代码,以了解它如何处理游标。您可能还想查看the PostgreSQL documentation for cursors

答案 2 :(得分: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)])