2

我正在使用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 查询或至少为我指明优化的方向,我会很高兴。

非常感谢你!

4

2 回答 2

4

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

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.

B-Tree 索引特征

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

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

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

于 2012-12-22T21:48:32.317 回答
0

去掉对LOWER函数的调用:在mysql中,LIKE忽略大小写,所以不需要调用。

于 2012-12-22T22:22:01.143 回答