最近在使用LIKE
和通配符搜索MS SQL数据库的最有效方式上,存在一场争论。我们正在使用%abc%
,%abc
和abc%
进行比较。一个人说过,在任期结束时你应该始终使用通配符(abc%
)。所以,据他们说,如果我们想找到以“abc”结尾的内容,那么使用`reverse(column)LIKE reverse('%abc')会是最有效的。SQL通配符搜索 - 效率?
我建立了一个测试使用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持有约500000条记录,大约有7400的地址是结束“街”,以及有关8,500个地址中有“街道”,但不一定在最后。每次测试运行需要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秒内完成(每个查询的平均值为.3331),并在0.0228中找到平均值500的结果。
%STREET%
在149.4500秒内完成(每个查询平均值为.2989),平均值为0.0177。 (每结果更快的时间,因为它找到比其它的词,在类似的时间。)
reverse(ADDRESS) like reverse('%STREET')
在134.0115秒(每个查询0.2680平均)完成,并且平均在0.0183秒发现500个结果。
reverse('TREETS%')
在167.6960秒(每个查询的平均值为.3354)中完成,并且在0.0229中找到平均500个结果。
我们预计该测试显示%STREET%
将是整体上最慢的,而它实际上是运行速度最快的,并且具有最好的平均返回500次结果的时间。虽然建议的reverse('%STREET')
是整体运行速度最快的,但返回500个结果的时间稍慢。
额外的乐趣:当我们运行测试时,一位同事在服务器上运行了分析器,发现使用双通配符会显着增加CPU使用率,而其他测试则相差1-2%。
是否有任何SQL效率专家可以解释为什么在搜索字符串末尾使用通配符会比开始时更好练习,也许为什么在字符串开头和末尾使用通配符搜索更快比刚开始使用通配符还要多?
DID名称您在每次测试之前清除缓冲区和缓存? – 2012-08-03 12:33:30
是的,在每次查询测试之前,我们重新启动服务器以确保它是一个公平测试。 – Jeremy1026 2012-08-03 12:35:16
reverse()方法将强制进行表扫描,因为每行必须颠倒过来,它通常与前缀通配符+预计算的反向列一起使用 – 2012-08-03 12:35:24