2012-03-15 79 views
4

對於帶有自動完成機場輸入字段,目前有一個表,說明機場,autocomplete_airport提高MySQL LIKE查詢的速度?

lang | description (with INDEX)       | ... 
-----+----------------------------------------------------+---- 
pt | New York - John F Kennedy (JFK), Estados Unidos | ... 
pt | Nova Iorque - John F Kennedy (JFK), Estados Unidos | ... 
... 

自動完成適用於單個單詞。所以當用戶輸入「yor」時,「紐約」出現(如果在LIMIT中)。該查詢目前工作如下:

SELECT * FROM autocomplete_airport WHERE lang = "pt" 
AND (description LIKE "%(yor)%" 
    OR description LIKE "yor%" 
    OR description LIKE "% yor%") 
ORDER BY description 
LIMIT 15 

現在我不知道如何加快速度。一種想法是創建下面的數據庫結構,表autocomplete_airportautocomplete_airport_word

id | lang | description (with INDEX)       | ... 
-----+------+----------------------------------------------------+---- 
123 | pt | New York - John F Kennedy (JFK), Estados Unidos | ... 
124 | pt | Nova Iorque - John F Kennedy (JFK), Estados Unidos | ... 
... 

word (with INDEX) | autocomplete_airport_id 
------------------+------------------------ 
New    |      123 
York    |      123 
John    |      123 
F     |      123 
Kennedy   |      123 
JFK    |      123 
... 

然後選擇只需要在字符串的開始搜索:

SELECT DISTINCT autocomplete_airport.* 
FROM autocomplete_airport 
INNER JOIN autocomplete_airport_word 
ON autocomplete_airport.id = autocomplete_airport_word.autocomplete_airport_id 
WHERE lang = "pt" 
AND word LIKE "yor%" 
ORDER BY description 
LIMIT 15 

那是新的結構值得的麻煩?它真的會加快速度嗎?有一種更簡單的方法嗎?

更新

只注意到了字表有一個缺陷。結果是:搜索「紐約」不會給出任何結果。什麼應該工作:

term (with INDEX)        | autocomplete_airport_id 
------------------------------------------------+------------------------ 
New York - John F Kennedy (JFK), Estados Unidos | 123 
York - John F Kennedy (JFK), Estados Unidos  | 123 
John F Kennedy (JFK), Estados Unidos   | 123 
F Kennedy (JFK), Estados Unidos     | 123 
Kennedy (JFK), Estados Unidos     | 123 
(JFK), Estados Unidos       | 123 
Estados Unidos         | 123 
Unidos           | 123 
JFK            | 123 
+1

這樣做! – fancyPants 2012-03-15 09:56:16

回答

5

由於MartinK說,如果你的表中有隻有幾百行,您的查詢應該是相當快速即使沒有優化 - 值得檢查發生了什麼。

但是,搜索文本字段的最佳方式是使用全文索引(http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html) - 這是精確設計的你正在描述的情況。

+0

我不確定有關mysql全文索引功能。然而,'布爾全文搜索'(和*通配符)的確對這個問題看起來很有用。我有點害怕'停用詞'和'阻塞'(默認情況下不啓用)會給用戶帶來一些意想不到的結果。因人而異。無論如何,upvoted :) – MartinK 2012-03-15 10:46:35

+0

看起來像最好的解決方案。但是,還沒有申請,因爲我首先需要我的客戶批准。在這種情況下添加索引並不容易,因爲整個數據庫都是InnoDB(出於很好的理由),並且系統中不提供將單個表更改爲MyISAM的功能。儘管如此,我還是想過解決這個問題的一種方法。 – feklee 2012-03-19 16:31:42

4

您建議的方法可能會加快您的查詢。 LIKE查詢的重要之處在於通配符%不能位於模式的開頭。

LIKE '%foobar'無法使用索引。 LIKE 'foobar%'可以使用索引。

但是,如果你只是有幾百個機場來存儲我會認爲三次,如果一個全表掃描真的很傷害。

使用EXPLAIN select {rest of query}找出如何以及如果數據庫正在使用。

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html (向下滾動到B樹索引特性,這是默認的MySQL索引類型)

+0

很高興知道'LIKE'%foobar''不能使用索引。事實上,這就是'EXPLAIN select {rest of query}'節目。現在我正在考慮是否使用全文搜索或我最初提出的獨立* word table *。順便說一句,每個「lang」大約有10,000個條目。應該做一些分析... – feklee 2012-03-15 15:57:51

+0

解決它'只是'添加索引並修改您的查詢有點聽起來非常誘人。我相信機場表中的數據是不變的,所以MyIsam表格在這裏很好(你可以不時地做'LOCK TABLE':)。我會給它一個鏡頭。祝你好運 – MartinK 2012-03-15 16:38:46