2010-09-23 78 views
4

我的數據庫在mysql v5.x上運行。我有一個有5列的表T1,列C1是主鍵。 C1的類型是varchar(20)。它包含了像值約2000行:如何在mysql查詢中使用索引效率

fxg 
axt3 
tru56 
and so on.. 

現在我的應用程序的任務是讀取輸入數據,發現如果輸入數據具有類似於表T1列C1發現了一個起步模式。例如:我的輸入可能顯示爲:

trx879478986 
    fxg87698x84 
    784xtr783utr 
    axt3487ghty 
... and so on 

因此,對於上面的輸入,我不得不返回「fxg87698x84」和「axt3487ghty」真假他人。我使用的查詢是:

select 1 from T1 where (? like concat(C1,'%')); 
note: the ? is replaced by the input value got from the application. 

的問題是我投入是巨大的(約1萬條記錄在30分鐘內被處理)和我的查詢速度不夠快。有關如何重新編寫查詢或強制使用索引的任何想法?即使我必須使用不同的對象結構,如果有幫助的話,我也可以做到。所以任何幫助將不勝感激。謝謝。

回答

2

你的問題的設置方式,你幾乎按照定義需要檢查數據庫中的每一行,對照每一個輸入,按照你當前的方式進行。在這種情況下,索引並不重要,因爲任何一行都可以匹配。

我不確定它會更快,但您可以嘗試的一件事是查詢數據庫,以便在您的輸入的每個可能有效的子字符串上進行完全匹配。

例如,如果你知道你的子字符串必須至少長3相匹配,開始第3個字符: trx879478986 => TRX,trx8,trx87,...

創建數組這些可能的匹配,並使用IN()運營商查詢他們:

SELECT 1 FROM T1 WHERE c1 IN ($array_of_strings); 

我敢肯定的MySQL可以使用索引來匹配給IN()

+0

我要建議 - 只有我增加了一個「ORDER BY CHAR_LENGTH(C1)」爲有利於比賽的「 ATX12345'對'ATX' – symcbean 2010-09-23 12:47:13

+0

+1,我正在輸入。這確實使用了索引,並且通過避免使用LIKE來避免如果C1包含'%'或'_'字符會發生什麼問題。 – bobince 2010-09-23 12:49:50

+0

Thx爲輸入。但是我必須做的有效子串的組合是3個字符到20個字符,而額外的處理類型可以抵消我可能獲得的性能增益。 – Abdullah 2010-09-23 13:21:50

9

你湊值的列表LD嘗試前N個查詢,找到第一個候選,然後應用候選人,以實際的模式:

select 1 
    from (select c1 
      from junk 
     where c1 <= 'fxg87698x84' 
     order by c1 desc limit 1) tmp 
where 'fxg87698x84' like concat(c1, '%'); 

前N個查詢應該在C1上使用常規指標。

編輯: 解釋說,在更詳細的在我的博客:http://blog.fatalmind.com/2010/09/29/finding-the-best-match-with-a-top-n-query/

+0

美麗!!這真的有助於減少我的全表掃描。 thx再次。 - Abdullah – Abdullah 2010-09-23 13:16:50

+0

@Abdullah答案是不正確的。比較'fxg'<='fxg87698x84'會返回1.但是比較'exg'<='fxg87698x84'也會返回1,這不能滿足實際需求。 – 2017-02-22 03:24:25