如何优化这个MySQL查询的运行时?

时间:2012-12-22 21:46:21

标签: mysql performance

我正在使用geonames.org的地理空间数据库。我目前在我的网站上有一个自动完成输入字段,它将搜索字词转发到数据库并返回适当的结果。一个重要的是,结果必须按国家排序。

我选择的表大约有900.000行,并使用:

创建
CREATE TABLE IF NOT EXISTS `geonames` (
`id` integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
`country_code` char(2) NOT NULL,
`postal_code` varchar(20) NOT NULL,
`place_name` varchar(180) NOT NULL,
...
FULLTEXT(country_code),
FULLTEXT(postal_code),
FULLTEXT(place_name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

典型的陈述如下:

SELECT postal_code, place_name FROM geonames WHERE LOWER(`place_name`)
LIKE 'washin%' ORDER BY FIELD (country_code, 'JE', 'GB', 'FR', 'LI', 'CH',
'DK', 'LU', 'BE', 'NL', ... many more countries in that list ... ) DESC;

我使用 FULLTEXT 索引来加速WHERE place_name LIKE 'washin%'部分。但是查询仍然有点慢。 SQL查询的任务是搜索表中与place_name匹配的每个'washin%',然后根据指定的国家/地区对结果进行排序。由于一次请求大量数据,查询是否会变慢?如果是,我怎么能减少这个瓶颈的运行时间呢?

我无论如何都不是MySQL的专家,所以如果有经验的人可以帮助我加快显示的SQL查询速度,或者至少指出我要进行优化的方向,我会很高兴。

非常感谢!

2 个答案:

答案 0 :(得分:4)

你应该避免在where子句中使用LOWER,因为这样就无法有效地使用索引:

SELECT postal_code, place_name FROM geonames
WHERE `place_name` LIKE 'washin%'
ORDER BY FIELD(country_code, 'JE', 'GB',  ...) DESC;

相反,您应该使用不区分大小写的排序规则。以_ci结尾的排序规则不区分大小写。区分大小写的排序规则以_cs结尾。

此外,您的全文索引将帮助您使用LIKE进行查询。您应该在place_name上使用a B-TREE index

  

B树索引特征

     

B树索引可用于使用=,>,> =,<,< =或BETWEEN运算符的表达式中的列比较。如果LIKE的参数是一个不以通配符开头的常量字符串,则该索引也可用于LIKE比较。

您还可以选择在索引中包含country_codepostal_code(但不包括第一列)。然后,这将为您的查询提供覆盖索引。

由于ORDER BY调用,FIELD也无法有效使用索引,但如果返回的结果数量相对较小,那么这应该不是问题。

答案 1 :(得分:0)

删除对LOWER函数的调用:在mysql中,LIKE忽略大小写,因此您无需调用它。