最近以最有效的方式使用搜索MS SQL数据库进行了辩论 LIKE
和通配符。我们正在比较使用 %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秒(每个查询平均值.3331)完成,平均在.0228中找到500个结果。
%STREET%
在149.4500秒内完成(每个查询平均值为.2989),在.0177中找到平均500个结果。 (每个结果的更快时间,因为它在相似的时间内找到比其他结果更多的结果。)
reverse(ADDRESS) like reverse('%STREET')
完成时间为134.0115秒(每次查询平均值为.2680),平均值为500秒,结果为.0183秒。
reverse('TREETS%')
在167.6960秒完成(每个查询的平均值为.3354),在.0229中找到平均500个结果。
我们期望这个测试能够证明这一点 %STREET%
这将是最慢的整体,而它实际上是最快的运行,并有最好的平均时间返回500结果。虽然建议 reverse('%STREET')
整体运行速度最快,但返回500个结果的速度要慢一些。
额外的乐趣:当我们运行测试时,同事在服务器上运行探查器,发现使用双通配符会显着增加CPU使用率,而其他测试则相互之间的1-2%。
是否有任何SQL效率专家可以解释为什么在搜索字符串末尾使用通配符比开头更好的做法,也许为什么在字符串的开头和结尾使用通配符进行搜索比使用通配符更快刚刚开始?