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 的成本正在减慢我的查询速度的主要内容,如果未能解决你的问题,请参考以下文章