在 postgresql 中优化潜在客户查询

Posted

技术标签:

【中文标题】在 postgresql 中优化潜在客户查询【英文标题】:Optimising a Lead query in postgresql 【发布时间】:2019-03-05 15:02:35 【问题描述】:

我想根据其名称和字母顺序选择一个实体,选择下一行的namename 列是一个 varchar,是唯一的并且有一个索引。

使用Lead 窗口函数,这是我想出的:

SELECT *
FROM (
    SELECT  
        *,
        LEAD("name", 1, '') OVER(ORDER BY name) AS next
    FROM entity    
    ORDER BY "name"
) results
WHERE "name" = 'CACTUS';

但是,随着实体表大小的增加,查询性能会下降。

查询计划如下:

Subquery Scan on results  (cost=0.42..31205.95 rows=1 width=299)
  Filter: ((results.""name"")::text = 'CACTUS'::text)"
  ->  WindowAgg  (cost=0.42..29002.24 rows=176297 width=299)"
        ->  Index Scan using ""IDX_2fbbd02c0f1ee2a4dda593705d"" on entity  (cost=0.42..26357.79 rows=176297 width=235)"

有没有更有效的方法来做到这一点?

postgresql 版本 11+

【问题讨论】:

lead() 没有 order by 并没有真正意义上的开始 - 没有“下一行”之类的东西,除非你指定一个 order by。但是是的,预计您拥有的行越多,这会越慢,因为内部查询必须对表中的 所有行进行排序 好的,我假设它会使用子查询的顺序,我已经更新了窗口函数以具有明确的 ORDER BY。 【参考方案1】:

您可以尝试不使用窗口函数和相关的标量子查询,但我不确定这是否真的更快:

SELECT e1.name, 
       (select coalesce(max(name), '')
        from entity e2
        where e2.name > e1.name) as next
FROM entity e1
WHERE e1.name = 'CACTUS';

【讨论】:

谢谢,这对我来说工作速度要快几个数量级,但我必须在子查询和查询中添加 ORDER BY。我还更新了问题以反映我想要一个订单:D。如果几天后没有其他答案,我会接受这个答案。 @shusson:但您声称 name 是唯一的,因此条件 where e1.name = 'CACTUS' 只能返回一行 - 我不明白您为什么需要 order bymax()> 的使用确实对选择“下一个”名称施加了顺序 是的,但我对基于特定顺序的下一行的名称感兴趣,比如按字母顺序。 @shusson:条件e2.name > e1.name 强加命令 是的,我会更新问题以强制按字母顺序

以上是关于在 postgresql 中优化潜在客户查询的主要内容,如果未能解决你的问题,请参考以下文章

如何优化在 postgresql 中查询这些数据?

在同一查询中选择和更新 PostgreSQL 以进行优化

优化 PostgreSQL 中的 SQL 查询

优化在 pgAdmin 中执行速度比在应用程序中更快的 postgresql 查询以及并发查询

针对多个表优化缓慢的 postgresql 查询

PostgreSQL 分组错误