SORT 的成本正在减慢我的查询速度

Posted

技术标签:

【中文标题】SORT 的成本正在减慢我的查询速度【英文标题】:Cost of SORT is slowing down my query 【发布时间】:2011-09-13 21:06:36 【问题描述】:

PostgreSQL 7.4(是的升级)

所以在我的 WHERE 条件下,我有这个

AND CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text 
        OR "substring"(t."FieldID"::text, 0, 4) = '123'::text 
        OR "substring"(t."FieldID"::text, 0, 5) = '5555'::text 
        OR "substring"(t."FieldID"::text, 0, 6) = '44444'::text 
        OR "substring"(t."FieldID"::text, 0, 3) = '99'::text 
    THEN 1
    ELSE 0
END = 1

替代语法但成本没有变化

AND CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 4) = '123'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 5) = '5555'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 6) = '44444'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 3) = '99'::text THEN 1    
    ELSE 0
END = 1

寻找一种成本有效的方法来通过字符串的开头限制结果。因此,如果字符串以 01、123、5555、44444 或 99 开头,则将其添加到结果集中。

有什么想法吗?

注意:FieldID 已编入索引 查看解释数据以查看查询中的瓶颈,当添加上述代码时,排序成本会大幅上升并减慢数据集/结果的返回速度。

解释的输出:

Sort (cost=88716.84..88719.89 rows=822 width=64)

由于查询很复杂,还有很多问题,但是如果我删除部分代码,排序成本就会下降

【问题讨论】:

a 在架构定义时已知的前缀('01''123' 等)还是依赖于单个查询? 这是一个包含整数的数据字段 我的意思是每个查询的前缀总是相同的,或者您是否在每个查询中寻找不同的前缀集? sry 是的,我只需要查找那些前缀,它们不会改变,但将来可以添加。这么多 【参考方案1】:

如果您只是按起始字符过滤,则可以使用like 没有问题,它只会使用索引。

AND (t."FieldID"::text LIKE '01%' OR 
     t."FieldID"::text LIKE '123%' OR 
     t."FieldID"::text LIKE '5555%' OR
     t."FieldID"::text LIKE '44444%' OR
     t."FieldID"::text LIKE '99%')

【讨论】:

这会比 RegEx 更快吗? t."FieldID" ~'^01' @Phill,在这个例子中是的,很难使用正则表达式的索引。但是你可以在其他情况下建立一个正则表达式索引。【参考方案2】:

您可能会通过定义与查询匹配的表达式索引来获得一些牵引力;像

CREATE INDEX t_fieldid_prefix_3 ON t (("substring"("FieldID"::text, 0, 3)))
CREATE INDEX t_fieldid_prefix_4 ON t (("substring"("FieldID"::text, 0, 4)))
CREATE INDEX t_fieldid_prefix_5 ON t (("substring"("FieldID"::text, 0, 5)))
CREATE INDEX t_fieldid_prefix_6 ON t (("substring"("FieldID"::text, 0, 6)))

如果您一直在寻找相同的前缀,请将整个内容包含在索引中:

CREATE INDEX t_fieldid_prefix ON t((CASE
    WHEN "substring"("FieldID"::text, 0, 3) = '01'::text 
        OR "substring"("FieldID"::text, 0, 4) = '123'::text 
        OR "substring"("FieldID"::text, 0, 5) = '5555'::text 
        OR "substring"("FieldID"::text, 0, 6) = '44444'::text 
        OR "substring"("FieldID"::text, 0, 3) = '99'::text 
    THEN 1
    ELSE 0
END))

【讨论】:

即使 FieldID 已经是索引,这样的事情会起作用吗? 查看syntax for 7.3,您可能必须定义一个函数来支持后一种情况,因为它似乎不允许任意表达式。 FieldID 的索引不会加速对复杂表达式(如substring())的过滤;但是表达式索引可以让查询规划器直接查找匹配的行。【参考方案3】:

我不知道您的旧版本是否支持这一点,但您可以尝试在排序表达式上创建一个索引,看看是否可以改进查询:

CREATE INDEX idx_case ON the_table (
  (CASE
      WHEN substring("FieldID", 0, 3) = '01' THEN 1
      WHEN substring("FieldID", 0, 4) = '123' THEN 1
      WHEN substring("FieldID", 0, 5) = '5555' THEN 1
      WHEN substring("FieldID", 0, 6) = '44444' THEN 1
      WHEN substring("FieldID", 0, 3) = '99' THEN 1    
      ELSE 0
  END));

对于当前版本,我很确定这可以用来改进 ORDER BY 步骤

【讨论】:

即使 FieldID 已经是索引,这样的事情会起作用吗? @Phil:可以,因为(完整)索引表达式不同。【参考方案4】:

根据此类查询的运行频率以及存在的数据量,您可能会考虑在查询之外计算其中的一些,并添加额外的列以仅用作索引。与数据仓库非规范化以加快报告查询的方式相同。

【讨论】:

大约 500,000 条记录,它是一个具有大量索引的大量使用数据库。该查询将在一天中运行多次,这就是我正在寻找性能调整的原因

以上是关于SORT 的成本正在减慢我的查询速度的主要内容,如果未能解决你的问题,请参考以下文章

如何减慢postgresql服务器的速度?

为啥没有聚合的结束 Group By 会减慢我的查询速度?

为啥有些列会减慢查询速度

与分页相关的哪些 LINQ 操作可能会减慢我的查询速度?

查询减慢网站速度,必须使它们执行得更快

MS Access 日期范围函数减慢查询速度