【问题标题】:Query performance with sorting in postgres在 postgres 中使用排序查询性能
【发布时间】:2021-05-04 09:33:22
【问题描述】:

我在对具有 33m 行的表进行查询时遇到了性能问题。查询应返回 6m 行。 我试图在没有任何明显延迟的情况下实现对请求的响应。我的应用程序中的数据流需要它。 启动后,数据传输可能需要更长的时间。困难在于查询有排序。 因此,我创建了一个索引,其中包含在“order by”语句和“where”子句中使用的字段。

这样的例子:

CREATE TABLE Table1 (
   Id SERIAL PRIMARY KEY,
   Field1 INT NOT NULL,
   Field2 INT NOT NULL,
   Field3 INT NOT NULL,
   Field4 VARCHAR(200) NOT NULL,
   CreateDate TIMESTAMP,
   CloseDate TIMESTAMP NULL
);
CREATE INDEX IX_Table1_SomeIndex ON Table1 (Field2, Field4);

查询喜欢这样:

SELECT * FROM Table1 t
WHERE t.CreateDate >= '2020-01-01' AND t.CreateDate < '2021-01-01'
ORDER BY t.Field2, t.Field4

它会导致以下结果: 当我添加“LIMIT 1000”时,它会立即重新运行结果并构建以下计划: the plan with 'LIMIT'

当我在没有“LIMIT”的情况下运行时,它会“思考”大约一分钟并返回大约 16 分钟的数据。它制定了以下计划: the plan with 'LIMIT'

为什么计划不同?

你能帮我立即制作souliton(没有限制)吗?

谢谢!

【问题讨论】:

  • 日期范围有多固定?

标签: sql postgresql performance sorting streaming


【解决方案1】:

您需要使用服务器端光标或类似的东西才能使其工作。否则,它会在返回任何结果之前运行查询完成。默认情况下没有“流媒体”。你如何做到这一点取决于你的客户,你没有提到。

如果您只是简单地声明一个游标,然后以块的形式获取,那么设置 cursor_tuple_fraction 将控制它是选择具有更快启动成本的计划(如您使用 LIMIT 获得的),还是更快的总体运行成本(就像你没有限制一样)。

【讨论】:

    【解决方案2】:

    如果“当我添加 LIMIT 1000 时,它会立即返回结果”并且您希望避免延迟,那么我建议您使用 LIMIT 1000 在循环中多次运行稍作修改的查询。一个重要的好处是不会有长时间运行的事务。

    在循环中多次运行的查询应该返回从上一次迭代运行中(field2, field4) 的最大值之后开始的记录。

    SELECT * 
      FROM table1 t
     WHERE t.CreateDate >= '2020-01-01' AND t.CreateDate < '2021-01-01'
       AND (t.field2, t.field4) > (:last_run_largest_f2_value, :last_run_largest_f4_value) 
     ORDER BY t.field2, t.field4
     LIMIT 1000;
    

    last_run_largest_f2_valuelast_run_largest_f4_value 是参数。它们的值应来自上一次迭代返回的最后一条记录。
    AND (t.field2, t.field4) &gt; (:last_run_largest_f2_value, :last_run_largest_f4_value) 在第一次迭代中应省略。

    • 重要限制

    这是OFFSET 的替代方法,如果(field2, field4) 值是唯一的,它将正常工作

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 2018-08-26
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2018-11-17
      • 2012-07-07
      相关资源
      最近更新 更多