【发布时间】:2010-10-31 10:00:15
【问题描述】:
我有一个 mysql (5.0.22) myisam 表,其中大约有 300k 条记录,我想在 5 英里半径范围内进行纬度/经度距离搜索。
我有一个涵盖纬度/经度字段的索引,当我只选择经度/经度时,它的速度很快(毫秒响应)。但是当我选择表格中的其他字段时,速度会慢到 5-8 秒。
我正在使用 myisam 来利用全文搜索。其他索引表现良好(例如 select * from Listing where slug = 'xxxxx')。
如何优化我的查询、表或索引以加快速度?
我的架构是:
CREATE TABLE `Listing` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(125) collate utf8_unicode_ci default NULL,
`phone` varchar(18) collate utf8_unicode_ci default NULL,
`fax` varchar(18) collate utf8_unicode_ci default NULL,
`email` varchar(55) collate utf8_unicode_ci default NULL,
`photourl` varchar(55) collate utf8_unicode_ci default NULL,
`thumburl` varchar(5) collate utf8_unicode_ci default NULL,
`website` varchar(85) collate utf8_unicode_ci default NULL,
`categoryid` int(10) unsigned default NULL,
`addressid` int(10) unsigned default NULL,
`deleted` tinyint(1) default NULL,
`status` int(10) unsigned default '2',
`parentid` int(10) unsigned default NULL,
`organizationid` int(10) unsigned default NULL,
`listinginfoid` int(10) unsigned default NULL,
`createuserid` int(10) unsigned default NULL,
`createdate` datetime default NULL,
`lasteditdate` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`lastedituserid` int(10) unsigned default NULL,
`slug` varchar(155) collate utf8_unicode_ci default NULL,
`aclid` int(10) unsigned default NULL,
`alt_address` varchar(80) collate utf8_unicode_ci default NULL,
`alt_website` varchar(80) collate utf8_unicode_ci default NULL,
`lat` decimal(10,7) default NULL,
`lon` decimal(10,7) default NULL,
`city` varchar(80) collate utf8_unicode_ci default NULL,
`state` varchar(10) collate utf8_unicode_ci default NULL,
PRIMARY KEY (`id`),
KEY `idx_fetch` USING BTREE (`slug`,`deleted`),
KEY `idx_loc` (`state`,`city`),
KEY `idx_org` (`organizationid`,`status`,`deleted`),
KEY `idx_geo_latlon` USING BTREE (`status`,`lat`,`lon`),
FULLTEXT KEY `idx_name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC;
我的查询是:
SELECT Listing.name, Listing.categoryid, Listing.lat, Listing.lon
, 3956 * 2 * ASIN(SQRT( POWER(SIN((Listing.lat - 37.369195) * pi()/180 / 2), 2) + COS(Listing.lat * pi()/180) * COS(37.369195 * pi()/180) * POWER(SIN((Listing.lon --122.036849) * pi()/180 / 2), 2) )) rawgeosearchdistance
FROM Listing
WHERE
Listing.status = '2'
AND ( Listing.lon between -122.10913433498 and -121.96456366502 )
AND ( Listing.lat between 37.296909665016 and 37.441480334984)
HAVING rawgeosearchdistance < 5
ORDER BY rawgeosearchdistance ASC;
在没有地理搜索的情况下解释计划:
+----+-------------+------------+--------+------ -----------+-----------------+---------+------+--- ---+--------------+
|编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 |
+----+-------------+------------+-------+--------- --------+-----------------+---------+------+------ +--------------+
| 1 |简单 |上市 |范围 | idx_geo_latlon | idx_geo_latlon | 19 |空 |第453章使用位置 |
+----+-------------+------------+-------+--------- --------+-----------------+---------+------+------ +--------------+
用地理搜索解释计划:
+----+-------------+------------+-------+--------- --------+-----------------+---------+------+------ +------------------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+------------+-------+--------- --------+-----------------+---------+------+------ +------------------------------+ | 1 |简单 |上市 |范围 | idx_geo_latlon | idx_geo_latlon | 19 |空 |第453章使用哪里;使用文件排序 | +----+-------------+------------+-------+--------- --------+-----------------+---------+------+------ +------------------------------+这是带有覆盖索引的解释计划。以正确的顺序排列列会产生很大的不同:
+----+-------------+--------+--------+------------- --+----------------+----------+------+--------+-- -------------------------------------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- --+----------------+----------+------+--------+-- -------------------------------------------------+ | 1 |简单 |上市 |范围 | idx_geo_cover | idx_geo_cover | 12 |空 |第453章使用哪里;使用索引;使用文件排序 | +----+-------------+--------+--------+------------- --+----------------+----------+------+--------+-- -------------------------------------------------+谢谢!
【问题讨论】:
-
发布快慢查询的解释计划。
-
看起来您在该表中有太多列。您可以通过稍微标准化您的数据结构来从查询中挤出一些性能。 :)
标签: mysql performance optimization geolocation query-optimization