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)
由于查询很复杂,但是如果我删除了部分代码,则排序成本会下降
答案 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)
根据运行此类查询的频率以及有多少数据,您可以考虑计算查询外部的一些内容,并添加额外的列以仅用作索引。与数据仓库非规范化以加速报告查询的方式相同。