2015-05-20 88 views
2

我越來越意識到提高查詢效率的重要性。關鍵是我有適當的索引等,以確保我的查詢不會佔用比真正需要的更多的IO。但是,這是一個醜陋的查詢,我不知道如何使它高效。SELECT ... WHERE值LIKE'%...%'

比方說,我有股項的表格,看起來像這樣在其最基本的形式:

CREATE TABLE StockItems (
    ItemID INT IDENTITY (1, 1) NOT NULL PRIMARY KEY, 
    SerialNo VARCHAR (50) NOT NULL 
); 

現在我需要編寫一個存儲過程,將返回所有庫存物品的任何序列號匹配提供的部分序列號。下面的查詢將實現正是:

SELECT * FROM StockItems WHERE SerialNo LIKE '%' + @SearchStr + '%' 

但是,當我看到一個查詢一樣,我在冷汗打破和離合器安慰我毯更緊。 SerialNo上沒有索引,即使有索引,考慮到我正在尋找部分匹配,這也無濟於事。

有沒有辦法用更高效的查詢來實現這個任務?

+0

恐怕沒有其他方法可以做到這一點(如果你希望它是部分匹配的話,效率會更高)。 – NickyvV

+2

這可能會有所幫助:http://stackoverflow.com/questions/7510646/like-vs-contains-on-sql-server – Tanner

+0

謝謝@NickyvV,我害怕那會是答案。但我仍然困惑。這當然不是一個完全不尋常的要求。現在我確定像亞馬遜這樣的大個子擁有更復雜的分佈式存儲和工作負載的服務器,但他們是如何做到的?如果我搜索部分書名,他們是否也必須瀏覽整個庫存池? –

回答

5

在文本中搜索單詞的問題與在序列號中快速搜索子串的問題完全不同。例如,倒排索引是文本分析的一個組成部分,但不太明顯的是要看看它們如何適用於您的問題。

你的問題是如何在實踐中完成。一個簡單的方法是硬件。在數據庫環境中,這將會把包含序列號的表釘入內存(如果表被大量使用並且不是太大,則默認情況下會發生),然後執行掃描。使用更多的線程/處理器可以使掃描速度更快,因此在問題中拋出硬件會有所幫助。

編寫自定義代碼(這將在亞馬遜或谷歌的情況下)將使該過程更快。

還有其他解決方案。如果字符串較大,則可以使用n-gram對字符串進行編碼。 N-gram(在這種情況下)是字符序列,例如3長,出現在字符串中(更多information)。

對於每個序列號,您分解所有n-gram序列並將它們存儲在一個大的索引表中。然後,查找搜索字符串中的所有n元組。首先,只得到具有相同n-gram組的序列號。然後對其進行蠻力搜索。

舉例來說,如果你有序列號 '1234567890',那麼它具有以下卦:123,234,456,567,678,789,890

如果您正在尋找%1919%那麼任何匹配字符串需要有191和919.第一個字符串既沒有,所以你不需要搜索它。