对于具有自动完成功能的机场输入字段,目前有一个包含机场描述的表autocomplete_airport
:
lang | description (with INDEX) | ...
-----+----------------------------------------------------+----
pt | New York - John F Kennedy (JFK), Estados Unidos | ...
pt | Nova Iorque - John F Kennedy (JFK), Estados Unidos | ...
...
自动完成适用于单个单词。因此,当用户输入“yor”时,则显示“new york”(如果在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_airport
和autocomplete_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只需要在字符串的开头搜索:
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
这种新结构值得吗?它会真的加快速度吗?有更简单的方法吗?
注意到 word表有一个缺陷。结果:搜索“纽约”不会给出任何结果。应该做些什么:
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
答案 0 :(得分:5)
正如MartinK所说,如果您的表只有几百行,即使没有优化,您的查询也应该非常快 - 值得检查发生了什么。
然而,搜索文本字段的最佳方法是使用全文索引(http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html) - 这是专为你正在描述的案例。
答案 1 :(得分:4)
您提出的方法可能会加快您的查询速度。关于LIKE查询的重要一点是,通配符%不能位于模式的开头。
LIKE '%foobar'
无法使用索引。
LIKE 'foobar%'
可以使用索引。
但是,如果 只有几百个机场要存储,那么如果全表扫描确实会伤害那么多,我会三思而后行。
使用EXPLAIN select {rest of query}
了解数据库是如何以及是否使用。
参见http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html (向下滚动到 B-Tree索引特征,这是默认的mysql索引类型)