Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 排序成本降低了我的查询速度_Sql_Postgresql_Case Statement_Query Performance - Fatal编程技术网

Sql 排序成本降低了我的查询速度

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

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 "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,在本例中是的,很难将索引与正则表达式一起使用。但在其他情况下,您可以构建正则表达式索引。