最近在使用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