代码之家  ›  专栏  ›  技术社区  ›  codeape

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

  •  6
  • codeape  · 技术社区  · 15 年前

    以下查询立即返回数据:

    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 是解决这个问题的关键。在我的例子中,我使用sqlacalchemy从python执行查询。 如何为单个查询设置该选项(由 session.execute ) ?我使用psycopg2驱动程序。

    专栏 time 是主键,btw。

    编辑:

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

    默认情况下,驱动程序一次收集查询的所有结果。对于大型数据集来说,这是不方便的,因此JDBC驱动程序提供了一种将结果集基于数据库光标的方法,并且只获取少量的行。

    将代码更改为光标模式非常简单,只需将语句的fetch大小设置为适当的大小。将fetch大小设置回0将导致缓存所有行(默认行为)。

    // make sure autocommit is off
    conn.setAutoCommit(false);
    Statement st = conn.createStatement();
    
    // Turn use of the cursor on.
    st.setFetchSize(50);
    
    2 回复  |  直到 15 年前
        1
  •  4
  •   Ants Aasma    15 年前

    psycopg2 dbapi驱动程序在返回任何行之前缓冲整个查询结果。您需要使用服务器端的光标以增量方式获取结果。有关SQL炼金术,请参见 server_side_cursors in the docs 如果你使用ORM, Query.yield_per() method .

    SQLAlchemy当前没有为每个查询设置该选项,但是 there is a ticket with a patch for implementing that .

        2
  •  0
  •   Carl Smotricz    15 年前

    理论上,因为您的ORDERBY是按主键排序的,所以不需要某种结果,而且DB确实可以立即按键顺序返回数据。

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

    如果限制为100,您不会注意到任何影响,因为从数据库中提取100个结果很快,并且如果在将结果发送给客户之前,首先对它们进行收集和排序,您不会注意到任何延迟。

    我建议试着把订单放在旁边。很有可能,您的结果将被正确地按时间排序(考虑到您的pk,甚至可能有一个标准或规范要求这样做),并且您可能更快地获得结果。