为什么postgresql不会立即开始返回行?

时间:2010-01-08 12:56:51

标签: python sql postgresql sqlalchemy

以下查询立即返回数据:

SELECT time, value from data order by time limit 100;

如果没有limit子句,服务器开始返回行需要很长时间:

SELECT time, value from data order by time;

我通过使用查询工具(psql)和使用API​​查询来观察这一点。

问题/问题:

  • 对于两个select语句,服务器在开始返回行之前必须完成的工作量应该相同。正确的吗?
  • 如果是这样,为什么案例2有延迟?
  • 是否存在一些我不理解的基本RDBMS问题?
  • 有没有办法让postgresql开始将结果行返回给客户端而不会暂停,对于案例2也是如此?
  • 编辑(见下文)。看起来setFetchSize是解决这个问题的关键。在我的例子中,我使用SQLAlchemy从python执行查询。 如何为单个查询设置该选项(由session.execute执行)?我使用psycopg2驱动程序。

time是主键,BTW。

修改

我相信JDBC driver documentation中的这段摘录描述了问题并提示了一个解决方案(我仍然需要帮助 - 请参阅上面的最后一个项目符号列表项目):

  

默认情况下,驱动程序会立即收集查询的所有结果。这对于大型数据集来说可能不方便,因此JDBC驱动程序提供了一种在数据库游标上建立ResultSet并仅获取少量行的方法。

  

将代码更改为游标模式就像将Statement的获取大小设置为适当的大小一样简单。将提取大小设置为0将导致缓存所有行(默认行为)。

// make sure autocommit is off
conn.setAutoCommit(false);
Statement st = conn.createStatement();

// Turn use of the cursor on.
st.setFetchSize(50);

2 个答案:

答案 0 :(得分:4)

psycopg2 dbapi驱动程序在返回任何行之前缓冲整个查询结果。您需要使用服务器端游标来逐步获取结果。对于SQLAlchemy,请参阅server_side_cursors in the docs,如果您正在使用ORM Query.yield_per() method

SQLAlchemy目前没有为每个查询设置的选项,只有there is a ticket with a patch for implementing that

答案 1 :(得分:0)

理论上,因为你的ORDER BY是主键,所以不需要一些结果,而DB确实可以按关键顺序立即返回数据。

我希望有能力的数据库注意到这一点,并对其进行优化。似乎PGSQL不是。 *耸肩*

如果您有LIMIT 100,则不会发现任何影响,因为它可以非常快速地将这100个结果从数据库中提取出来,如果它们在发货之前首先收集并排序,您将不会发现任何延迟给你的客户。

我建议尝试删除ORDER BY。很可能,你的结果会按时间正确排序(考虑到你的PK,甚至可能有一个标准或规范要求这样做),你可能会更快地得到你的结果。