Sql 排序成本降低了我的查询速度
PostgreSQL 7.4(Yep升级) 所以在我的情况下,我有这个Sql 排序成本降低了我的查询速度,sql,postgresql,case-statement,query-performance,Sql,Postgresql,Case Statement,Query Performance,PostgreSQL 7.4(Yep升级) 所以在我的情况下,我有这个 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 "substr
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开头,则将其添加到结果集中
有什么想法吗
注意:字段ID已编入索引
查看Explain数据以查看查询中的瓶颈,当添加上述代码时,排序的成本会大大增加并减慢数据集/结果的返回速度
Explain的输出:
Sort (cost=88716.84..88719.89 rows=822 width=64)
<> P>>查询复杂,但如果删除代码的一部分,排序成本会下降,这取决于运行这种查询的频率,也取决于有多少数据,您可能会考虑对查询外部进行计算,并添加额外的列作为索引使用。同样的方式,一个数据仓库去加速报告查询。 取决于运行这种查询的频率,也取决于有多少数据,您可以考虑计算一些外部的查询,并添加额外的列作为索引使用。与数据仓库反规范化以加速报告查询的方式相同。通过定义与查询匹配的表达式索引,您可能会获得一些吸引力;差不多
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))
通过定义与查询匹配的表达式索引,您可能会获得一些吸引力;差不多
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))
我不知道您的古代版本是否支持这一点,但您可以尝试在排序表达式上创建索引,看看这是否改善了查询:
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));
对于当前版本,我非常确定这可以用于逐步改进顺序我不知道您的旧版本是否支持这一点,但您可以尝试在排序表达式上创建索引,看看这是否可以改进查询:
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));
对于当前版本,我很确定这可以用于逐步改进顺序如果您只是按起始字符进行筛选,您可以像一样毫无问题地使用,它将只使用索引
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%')
如果您只是按起始字符进行筛选,那么可以像使用一样毫无问题地使用,它只会使用索引
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%')
a前缀(
'01'
,'123'
,等等)是在模式定义时已知的,还是依赖于单个查询?它是一个包含整数的数据字段,我的意思是每个查询的前缀总是相同的,还是在每个查询中查找不同的前缀集?是的,我只需要查找这些前缀,它们不会改变,但可以在将来添加到。因此,更多的前缀('01'
,'123'
等)是在模式定义时已知的,还是依赖于单个查询?这是一个包含整数的数据字段。我的意思是,每个查询的前缀总是相同的,还是在每个查询中查找不同的前缀集?是的,我只需要寻找那些前缀,它们不会改变,但可以添加到未来。因此,其中更多的是大约500000条记录,这是一个使用率很高的数据库,有很多索引。该查询将在一天中运行多次,这就是为什么我要寻找一个大约500000条记录的性能调整,这是一个使用率很高的数据库,有很多索引。查询将在一天中运行多次,这就是为什么我要寻找一个性能调整,即使FieldID已经是索引,也会像这样工作吗?看看下面的示例,您可能需要定义一个函数来支持后一种情况,因为它似乎不允许使用任意表达式。FieldID的索引不会加速对复杂表达式(如substring()
)的过滤;但是表达式索引可以让查询计划器直接查找匹配的行。即使FieldID已经是索引,也可以这样做吗?查看下面的示例,您可能需要定义一个函数来支持后一种情况,因为它似乎不允许使用任意表达式。FieldID的索引不会加速对复杂表达式(如substring()
)的过滤;但是表达式索引可以让查询计划器直接查找匹配的行。即使FieldID已经是索引,也可以这样做吗?@Phil:可以,因为(完整的)索引表达式不同。即使FieldID已经是索引,也可以这样做吗?@Phil:可以,因为(完整的)索引表达式索引表达式不同。这会比正则表达式更快吗?t、 “FieldID”~'^01'@Phill,在本例中是的,很难将索引与正则表达式一起使用。但是你可以在其他情况下建立一个正则表达式索引。这会比正则表达式更快吗?t、 “FieldID”~'^01'@Phill,在本例中是的,很难将索引与正则表达式一起使用。但在其他情况下,您可以构建正则表达式索引。