2012-01-24 76 views
0

我有一個小問題,真的很感謝幫助。MySQL數字版相關搜索性能?

我有包含具有以下數據結構33000000行MyISAM表:

id -> Primary Key, Unsigned INT, Auto-Increment 
characters -> Unique Indexed, varchar(15) 
price -> decimal (10,2) 
active -> tinyint(1) 

我已經寫了一個腳本,從用戶採取搜索值,然後創建下面的查詢,基於所述用戶輸入在「凱文」:

SELECT characters, price 
FROM listings_dvla 
WHERE active=TRUE 
AND LOWER(REPLACE(characters, ' ', '')) REGEXP '^[a-z0-9]*[(k)]+[a-z0-9]?[(e)(3)]+[a-z0-9]?[(v)]+[a-z0-9]?[(i)(1)]+[a-z0-9]?[(n)(11)(1v)]+[a-z0-9]*' 
ORDER BY characters ASC 
LIMIT 0, 12 

只是爲了說明,正則表達式只是想匹配,以便每個字母,或意味着在「號牌的語言」,例如相同的字母序列。 N == 1V

事情是,這個查詢需要上帝該死的年齡! 20+秒。我一直在閱讀相當數量的文章,並發現將字符作爲主鍵的速度較慢,因此我將其添加並添加了一個ID字段。我使用了EXPLAIN,它顯示了索引,它們是NULL,我假設這是因爲REGEXP禁用它們(我也在某處讀過)。

我的問題是,有沒有人有任何明智的想法,嚴重增加這種查詢性能?因爲我覺得我不知道讓這個更快的事情非常重要。

如果需要,我會改變表格結構,所以不要擔心給我一個相當極端的答案。

感謝您閱讀本文,非常感謝您的任何建議。

+0

如果刪除字符列上的LOWER和REPLACE,時間是否有所不同?通常,您希望避免對where子句中的列執行字符串操作,因爲索引不太可能被使用。還可以用直接的'characters ='kevin'或完全匹配的東西來測試。您可能更適合在代碼中調整用戶輸入,而是運行多個查詢,而不是執行正則表達式匹配的一個查詢,並操縱您搜索的列。 – nos

回答

0

字符串查詢在mysql中很慢。我甚至不確定是否有任何按鍵(FULLTEXT除外)。

您使用在哪裏,這意味着條件每個記錄必須加載,以代替和更低的更新不是對正則表達式進行比較(MySQL已經無法事先知道結果會是怎樣的方式)功能。

基本上:使用這種正則表達式,你永遠不會有這個查詢快。

但是你可以添加字段,如isWord TINYINT DEFAULT 0(上面有指數)和使用查詢:

UPDATE listings_dvla SET isWord = 1 WHERE active=TRUE 
AND LOWER(REPLACE(characters, ' ', '')) REGEXP '^[a-z0-9]*[(k)]+[a-z0-9]?[(e)(3)]+[a-z0-9]?[(v)]+[a-z0-9]?[(i)(1)]+[a-z0-9]?[(n)(11)(1v)]+[a-z0-9]*' 

而不是選擇記錄由* 索引字段有:SELECT ... WHERE ... AND isWord = 1

+0

更新查詢將需要首先運行,因此需要只要正常搜索它就可以了?或者我在這裏誤解了你? –

+0

@KevinOrriss是的,首先它需要20多秒,但我無法想象它的工作更快 – Vyktor

0

首先,你可以「清理」字符字段,因此您不必將其轉換爲更低和去除空格。這一行爲幾乎肯定意味着您錯過了任何索引的好處。

其次,明顯的替代方案是「在」查詢運行的修改「凱文」到客戶端上的各種號牌形式的代碼,並轉換成這樣:

select * 
from listings_dvla 
where active = 1 
and cleaned_characters in ('kev1n', 'kev1iv'.....) 

如果你也想能夠在字符中搜索單詞 - 例如,返回參數KEV的A10 KEV,可以通過使用子字符串創建附加列來作弊。

表listings_dvla

ID characters cleaned_characters characters_right7 characters_right6 characters_right5 characters_right4 characters_right3 
1  A10 KEV  a10kev    10kev    0kev    kev  
2  KT 11 TCP  kt11tcp    t11tcp    11tcp   1tcp  tcp  

髒,而是通過創建的所有列的索引,你應該能夠得到非常快速的查詢。插入/更新將會更慢,儘管...

+0

可以說我搜索「kev」,您的查詢將無法找到車牌號碼「A10 KEV」。搜索一個確切的看起來非常快,直到我嘗試使用LIKE或REGEXP纔會減慢。 –

+0

啊,沒錯 - 沒有看足夠詳細的reg exp來挑選。 LIKE和REGEXP幾乎肯定不會使用索引;修改了答案以顯示如何解決該問題。 –

0

因爲您沒有在您的where子句中使用ID字段,所以mysql沒有使用您的主鍵。那裏沒有驚喜。

我想,你需要的是你的角色列上的全文索引。