Oracle中的substr或LIKE更快?

时间:2009-07-28 22:07:13

标签: sql oracle

WHERE substr(my_field,1,6) = 'search'

WHERE my_field LIKE 'search%'

在Oracle中更快,还是没有区别?

6 个答案:

答案 0 :(得分:20)

假设最高性能是目标,我最好选择SUBSTR(my_field,1,6)并创建一个基于函数的索引来支持查询。

CREATE INDEX my_substr_idx
    ON my_table( substr( my_field,1,6 ) );

正如其他人指出的那样,SUBSTR(my_field,1,6)无法在MY_FIELD上使用常规索引。 LIKE版本可能使用索引,但在这种情况下优化器的基数估计通常相当差,因此很可能在有用时不使用索引,或者在表扫描更可取时使用索引。索引实际表达式将为优化器提供更多信息,因此更有可能正确选择索引。比我聪明的人可能能够建议一种方法来使用11g中的虚拟列统计信息来为优化器提供更好的LIKE查询信息。

如果6是一个变量(即你有时想搜索前6个字符,有时想搜索不同的数字),你可能无法提出基于函数的索引来支持该查询。在这种情况下,你可能会更好地利用LIKE公式中的优化器决策的变幻莫测。

答案 1 :(得分:9)

在提供的两个选项中,绝对是喜欢的。必须对表中的所有行执行substring方法。使用LIKE将允许使用索引。

要检查我的答案,只需分析结果。应该清楚这一天。

答案 2 :(得分:2)

如果my_field上有索引,那么LIKE可能会更快。做自己的基准测试。

答案 3 :(得分:2)

如果你有没有索引而没有差别。因为oracle正在进行全表扫描并评估每行的表达式。 您可以在列上放置索引以加快查询速度。

CREATE INDEX my_like_idx
ON my_table( my_field );

此索引更灵活,可以使用like来加快查询速度。它适用于从字符开始并在结尾处有占位符(%)的任何比较。 Oracle正在进行索引范围扫描以查找所有匹配的行。

CREATE INDEX my_substr_idx
ON my_table( substr( my_field,1,6 ) );

此索引使用substr加速查询。但索引非常特殊,只比较前6个字符。

如果你在中间查询一块。创建基于函数的索引将有所帮助。

WHERE substr(my_field,2,5) = 'earch'
WHERE my_field like '%earch%'

答案 4 :(得分:1)

这里真的有两个问题:

  1. Oracle将为哪一个产生更准确的基数和成本估算?
  2. 哪种方法在潜在的访问方法方面更灵活?
  3. 这可能因版本而异,但两者都非常容易测试,因此您可以确保获得最适合您的版本和数据的信息。

    使用...

    运行两个查询的执行计划
    explain plan for 
    select ... from ... where my_field LIKE 'search%';
    
    select * from table(dbms_xplan.display);
    

    explain plan for 
    select ... from ... where substr(my_field,1,6) = 'search';
    
    select * from table(dbms_xplan.display);
    

    您可能会看到执行计划的差异,具体取决于索引的存在等,但也会将基数估算值与您获得的实际结果进行比较:

    select count(*) from ... where my_field LIKE 'search%';
    

    这两种方法中的一种可能比另一种方法更准确。

    如果它们都不是非常准确这个查询预计会运行非常重要的时间,那么考虑使用动态采样来改进估计,因为错误的基数估计优化器无论如何,可能会选择次优的访问方法。

    explain plan for 
    select /*+ dynamic_sampling(4) */ ... from ... where substr(my_field,1,6) = 'search';
    
    select * from table(dbms_xplan.display);
    

    就索引使用而言,两种方法都可以使用基于索引的访问方法。 LIKE谓词可能更友好,可以使用范围扫描或快速全索引扫描。 SUBSTR方法当然可以使用快速全索引扫描,但是优化器是否会考虑范围扫描最好在您自己的版本上进行测试 - 我的回忆是它不会,但是谁会说substr(my_column, 1 ,n)不会被认为是特殊情况,如果现在不是将来呢?

答案 5 :(得分:0)

我会介绍两者。但我猜测'LIKE'会快得多,因为它在索引上使用二进制搜索(如果字段被索引)。如果使用SUBSTR方法,最终将进行全表扫描,因为Oracle必须逐行处理该函数。