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

时间:2011-09-13 21:06:36

标签: sql postgresql case-statement query-performance

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已编入索引 查看Explain数据以查看查询中的瓶颈,添加上述代码时,Sort的成本会上升并减慢数据集/结果的返回。

解释输出:

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

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

4 个答案:

答案 0 :(得分: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%')

答案 1 :(得分: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))

答案 2 :(得分: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步骤

答案 3 :(得分:0)

根据运行此类查询的频率以及有多少数据,您可以考虑计算查询外部的一些内容,并添加额外的列以仅用作索引。与数据仓库非规范化以加速报告查询的方式相同。