【问题标题】:SQL Wildcard Search - Efficiency?SQL 通配符搜索 - 效率?
【发布时间】:2012-08-01 12:07:15
【问题描述】:

最近关于使用LIKE 和通配符搜索MS SQL 数据库的最有效方法一直在争论。我们使用%abc%%abcabc% 进行比较。有人说过,您应该始终在学期结束时使用通配符 (abc%)。所以,根据他们的说法,如果我们想找到以“abc”结尾的东西,使用 `reverse(column) LIKE reverse('%abc') 是最有效的。

我使用 SQL Server 2008 (R2) 设置了一个测试来比较以下每个语句:

select * from CLMASTER where ADDRESS like '%STREET'
select * from CLMASTER where ADDRESS like '%STREET%'   
select * from CLMASTER where ADDRESS like reverse('TEERTS%')  
select * from CLMASTER where reverse(ADDRESS) like reverse('%STREET')

CLMASTER 拥有大约 500,000 条记录,大约有 7,400 个地址以“Street”结尾,大约 8,500 个地址中有“Street”,但不一定在结尾。每次测试运行耗时 2 秒,它们都返回了相同数量的行,除了 %STREET%,它发现了额外的 900 个左右的结果,因为它选择了末尾有公寓号的地址。

由于 SQL Server 测试在执行时间上没有显示出任何差异,我转而使用 PHP,在其中使用以下代码,在每个语句中切换,以快速运行多个测试:

<?php

    require_once("config.php");
    $connection = odbc_connect( $connection_string, $U, $P );

    for ($i = 0; $i < 500; $i++) {
    $m_time = explode(" ",microtime());
    $m_time = $m_time[0] + $m_time[1];

    $starttime = $m_time;

    $Message=odbc_exec($connection,"select * from CLMASTER where ADDRESS like '%STREET%'");
    $Message=odbc_result($Message,1);

    $m_time = explode(" ",microtime());
    $m_time = $m_time[0] + $m_time[1];

    $endtime = $m_time;

    $totaltime[] = ($endtime - $starttime);

}

odbc_close($connection);

echo "<b>Test took and average of:</b> ".round(array_sum($totaltime)/count($totaltime),8)." seconds per run.<br>";
echo "<b>Test took a total of:</b> ".round(array_sum($totaltime),8)." seconds to run.<br>";

?>

此测试的结果与在 SQL Server 中测试时的结果一样模棱两可。

%STREET 在 166.5823 秒内完成(每个查询平均 0.3331),平均 0.0228 找到 500 个结果。

%STREET% 在 149.4500 秒内完成(每个查询平均 0.2989),平均在 0.0177 中找到 500 个结果。 (每个结果的时间更快,因为它在相似的时间内找到比其他结果更多的结果。)

reverse(ADDRESS) like reverse('%STREET') 在 134.0115 秒内完成(每个查询平均 0.2680 个),平均在 0.0183 秒内找到 500 个结果。

reverse('TREETS%') 在 167.6960 秒内完成(每个查询平均 0.3354),平均 0.0229 找到 500 个结果。

我们预计此测试将显示 %STREET% 总体上是最慢的,而实际上它是运行最快的,并且返回 500 个结果的平均时间最好。虽然建议的 reverse('%STREET') 总体上运行速度最快,但返回 500 个结果的时间稍慢。

额外的乐趣:一位同事在我们运行测试时在服务器上运行分析器,发现使用双通配符会显着增加 CPU 使用率,而其他测试之间的差异在 1-2% 以内。

是否有任何 SQL 效率专家可以解释为什么在搜索字符串的末尾使用通配符比在开头更好的做法,也许为什么在字符串的开头和结尾使用通配符比搜索更快只是在开头使用通配符?

【问题讨论】:

  • 每次测试前你是否清除了缓冲区和缓存?
  • 是的,在测试每个查询之前,我们都会重新启动服务器以确保它是一个公平的测试。
  • reverse() 方法将强制进行表扫描,因为必须反转每一行,它通常与前缀通配符 + 预先计算的反向列一起使用
  • 即使模式以通配符开头,索引也可以减少 I/O,因为不需要扫描表行。覆盖索引也可以提高性能。

标签: sql sql-server sql-server-2008 query-optimization processing-efficiency


【解决方案1】:

在字符串末尾添加通配符,例如'abc%',将有助于如果该列被索引,因为它可以直接查找以'abc' 开头的记录并忽略其他一切。开头有通配符意味着它必须查看每一行,而不考虑索引。

好文章here有更多解释。

【讨论】:

  • 这意味着做reverse(col) like 'abc%'之类的事情是个坏主意。
  • 是的,REVERSE 或任何其他更改索引列的计算都意味着您失去了可搜索性。
  • 感谢您提供的答案/cmets
  • @AdamRobinson 没有反向不是坏主意,我也使用它,只需将反向值存储在新列中
【解决方案2】:

只有Like 字符串末尾的通配符才会使用索引。

如果您想提高字符串前后通配符的速度,您应该考虑使用 FTS Contains。还有see this related SO post regarding Contains versus Like

【讨论】:

  • 感谢您提供的答案,不幸的是,切换到 Contains 对我们来说不是一个可行的解决方案,因为我们需要对很多(成百个)表进行全文索引才能使其成为可行的解决方案.我们经常搜索特定的子字符串和其他项目。
【解决方案3】:

Microsoft 开始,保留结束通配符更有效,因为如果存在通配符,它​​可以使用索引而不是执行扫描。想想搜索是如何工作的,如果您不知道它之前是什么,那么您必须扫描所有内容,但如果您只搜索尾部,那么您可以对行进行排序,甚至可能(取决于您要查找的内容) ) 进行准二分搜索。

连接或谓词中的某些运算符往往会产生资源密集型操作。具有用通配符(“%a value%”)括起来的值的 LIKE 运算符几乎总是会导致表扫描。由于前面的通配符,这种类型的表扫描是一项非常昂贵的操作。只有关闭通配符的 LIKE 运算符可以使用索引,因为索引是 B+ 树的一部分,并且通过从左到右匹配字符串值来遍历索引。

所以,上面的引用也解释了为什么在运行两个通配符时会出现巨大的处理器峰值。它只是偶然地完成得更快,因为有足够的马力来掩盖效率低下。在尝试确定查询的性能时,您希望查看查询的执行而不是服务器的资源,因为这些可能会产生误导。如果我有一个足够强大的服务器来为天气服务,并且我正在对小至 500,000 行的表运行查询,那么结果将会产生误导。

除 Microsoft 引用您的答案这一事实外,在进行性能分析时,请考虑深入学习如何阅读执行计划。这是一项投资,非常枯燥,但从长远来看是值得的。

简而言之,无论谁指出仅使用尾随通配符更有效,都是正确的。

【讨论】:

  • @Jeremy1026 - 我已经更新了我的答案,对服务器性能使用的结果进行了更多说明。
  • 感谢您提供的答案。
【解决方案4】:

在 MS SQL 中,如果你想得到那些以 'ABC' 结尾的名字,那么你可以像下面这样查询(假设表名是student

select * from  student where student_name like'%[ABC]'

所以它会给出以 'A' ,'B','C' 结尾的名称。

2) 如果你想拥有以“ABC”开头的名字意味着-

select * from student where student_name like '[ABC]%'

3) 如果你想要名字中间有 'ABC'

select * from student where student_name like '%[ABC]%' 

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    相关资源
    最近更新 更多