LIKE
最近,关于使用和通配符搜索 MS SQL 数据库的最有效方法一直在争论。我们使用%abc%
、%abc
和进行比较abc%
。有人说过,您应该始终在术语末尾使用通配符 ( 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 效率专家可以解释为什么在搜索字符串的末尾使用通配符比在开头更好的做法,以及为什么在字符串的开头和结尾使用通配符搜索比使用通配符更快刚开始?