0

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)

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

4

4 回答 4

2

如果您只是按起始字符过滤,则可以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%')
于 2011-09-13T21:30:40.770 回答
1

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

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))
于 2011-09-13T21:20:34.830 回答
1

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

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 步骤

于 2011-09-13T21:21:15.363 回答
0

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

于 2011-09-13T21:12:33.877 回答