I have a myisam mysql table (5.0.22) with approximately 300 thousand records in it, and I want to search for distances in lat / lon within a radius of five miles.
I have an index that covers lat / lon fields and quickly (milisecond response) when I just select lat / lon. But when I select additional fields in the table, it slows down to 5-8 seconds.
I use myisam to use full-text search. Other indexes work well (for example, select * from the list where slug = 'xxxxx').
How to optimize my query, table or index to speed things up?
My scheme:
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;
My request:
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
Explain the plan without a geo-search:
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ------------- +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ------------- +
| 1 | SIMPLE | Listing | range | idx_geo_latlon | idx_geo_latlon | 19 | NULL | 453 | Using where |
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ------------- +
Explain the plan using geo-search:
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ----------------------------- +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ----------------------------- +
| 1 | SIMPLE | Listing | range | idx_geo_latlon | idx_geo_latlon | 19 | NULL | 453 | Using where; Using filesort |
+ ---- + ------------- + ------------ + ------- + --------- -------- + ----------------- + --------- + ------ + ------ + ----------------------------- +
Here is an explanation plan with a coverage index. The presence of columns in the correct order is of great importance:
+ ---- + ------------- + -------- + ------- + ------------- - + --------------- + --------- + ------ + -------- + ----- ------------------------------------- +
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+ ---- + ------------- + -------- + ------- + ------------- - + --------------- + --------- + ------ + -------- + ----- ------------------------------------- +
| 1 | SIMPLE | Listing | range | idx_geo_cover | idx_geo_cover | 12 | NULL | 453 | Using where; Using index; Using filesort |
+ ---- + ------------- + -------- + ------- + ------------- - + --------------- + --------- + ------ + -------- + ----- ------------------------------------- +
Thanks!