2009-10-08 46 views
4

開頭我聽說由於性能原因,不建議在SQL Server的LIKE子句的開頭使用%。爲什麼這樣呢?%like clause

關於此的一些更多詳細信息將幫助我理解此問題的影響。

回答

13

A %LIKE子句的開頭表示索引完全沒用。如果有靜態文本將模式錨定在%之前,至少可以從索引中獲得潛在效用。

+4

關鍵詞是「sargable」 – 2009-10-08 13:06:40

2

將它放在任何位置都會增加性能,因爲沒有關於文本字段內容的索引。

在開始時,它必須在最差的情況下搜索到文本字段的末尾。

+1

如果字段的開頭是固定的,則某些(可能是大多數)數據庫引擎將使用索引。就像搜索「Abc%」一樣,它可以使用索引查找第一個「Abc」,然後從那裏按順序搜索。但是,當字符串以「%」開頭時...查看所有其他答案。 – Jay 2009-10-08 13:29:02

5

%foo基本上說「所有以'foo'結尾的字符串」。爲了過濾掉這些,SQL服務器必須掃描所有表(在最壞的情況下)並檢查每個字符串。這就是爲什麼它如此昂貴。

2

如果在子句的開頭處有%,則查詢引擎無法生成使用索引但必須進行表掃描的查詢計劃。

5

爲什麼LIKE'%...'不好?您不能使用任何索引並且必須掃描整個表格。

這裏是一個很好的例子:

去電話簿,找到與「%CH」是我所有 名。這將 需要相當長的一段時間,因爲你不是 能夠使用聚集索引,並且必須掃描整本書!

鑑於數據「ABCDEFG」

WHERE Column1 LIKE '%cde%' --can't use an index 

WHERE Column1 LIKE 'abc%' --can use and index 

WHERE Column1 Like '%defg' --can't use an index, but see note below 

注:如果您有需要「%DEFG」重要問題,你可以使用,你扭轉持續計算列()列,然後指數它。你就可以查詢在:

WHERE Column1Reverse Like REVERSE('defg')+'%' --can use the persistent computed column's index 

添加一個持久化計算列(即反轉字符串)和指數就可以了,使用此代碼:

ALTER TABLE YourTable ADD ReversedYourString AS REVERSE(YourString) PERSISTED 

CREATE NONCLUSTERED INDEX IX_YourTable_ReversedYourString 
ON YourTable (ReversedYourString) 
0

全表掃描

DBA最害怕的是什麼;)

由於搜索無法通過索引加速,因此服務器必須遍歷表中的每條記錄(=表掃描)並檢查記錄是否與LIKE表達式匹配。

這對於小型表格可能不是問題,但對於有大量行的大型表格肯定會有問題,因爲所有記錄都必須從磁盤中提取。

這與索引掃描相反,在索引掃描中,搜索條件允許服務器使用索引將搜索限制在(理想情況下)較小的一組記錄中。

1

很多人解釋了爲什麼col1像'%...'一樣糟糕。

這裏有一個潛在的解決方法,如果你碰到這種情況很多:

  • 創建另一列說COL2
  • 寫在插入觸發/ COL1的更新填充COL2與COL1「倒退」
  • 在col2上創建索引
  • 如果您的應用程序必須搜索col1(如'%...'),則搜索col2(如'...%')而不是(甚至是substr(col1等)=')。 ..'[原諒我的oracle方言]

我們正在使用它來搜索VIN(車輛識別號碼)或社會安全號碼的最後幾位,它效果很好!性能改進非常好

+0

忘記使用觸發器,使用計算列效率更高。您只需要REVERSE()原始值,您可以使用我答案中的示例代碼搜索它。 – 2009-10-08 13:57:59

+0

計算列似乎是特定於SQLServer的,它當然是一個不錯的和優雅的解決方案。如前所述,我更像是一名Oracle人員。 – Thorsten 2009-10-08 18:12:56