How to INDEX this MySQL table for use with GEO data?
My table currently stands like this:
CREATE TABLE IF NOT EXISTS `x_geodata` (
`post_id` int(11) NOT NULL,
`post_type` varchar(20) NOT NULL,
`lat` float(10,6) NOT NULL,
`lng` float(10,6) NOT NULL,
PRIMARY KEY (`post_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
How do I correctly and efficiently INDEX this table?
The only query ran on this table is as follows:
if(!empty($_SESSION['s_property_radius'])) {$dist = $_SESSION['s_property_radius'];}else{$dist = 50;}
$orig_lat = $_SESSION['s_propert开发者_如何学运维y_address_lat'];
$orig_lon = $_SESSION['s_property_address_lng'];
$lon1 = $orig_lon - $dist / abs( cos( deg2rad( $orig_lat ) ) * 69 );
$lon2 = $orig_lon + $dist / abs( cos( deg2rad( $orig_lat ) ) * 69 );
$lat1 = $orig_lat - ( $dist / 69 );
$lat2 = $orig_lat + ( $dist / 69 );
$sql = "
SELECT `t`.`post_id`, 3956 * 2 * ASIN( SQRT( POWER( SIN( ( ".$orig_lat." - `t`.`lat` ) * pi() / 180 / 2), 2 ) + COS( ".$orig_lat." * pi() / 180) * COS( `t`.`lat` * pi() / 180 ) * POWER( SIN( ( ".$orig_lon." - `t`.`lng` ) * pi() / 180 / 2 ), 2 ) ) ) AS `distance` FROM (
SELECT `post_id`, `lat`, `lng` FROM `x_geodata` WHERE `post_type` = 'some post type' AND `lng` BETWEEN '".$lon1."' AND '".$lon2."' AND `lat` BETWEEN '".$lat1."' AND '".$lat2."'
) AS `t` HAVING `distance` <= ".$dist."
";
The query checks to make sure we are looking at the correct post type and then does a square radius check on the lat and lng. The returned results are then run through a circular radius check.
What I'm looking for is updated CREATE TABLE SQL or UPDATE TABLE SQL to get this INDEXED correctly.
Any help is greatly appreciated.
EDIT: Did an EXPLAIN on my query based on arnep answer and I got this:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
2 DERIVED zch_geodatastore range post_type post_type 70 NULL 3 Using where
No idea what it means though...
MySQL has got special SPATIAL
keys for MySQL.
See: http://dev.mysql.com/tech-resources/articles/4.1/gis-with-mysql.html
And a quote from: http://dev.mysql.com/doc/refman/5.1/en/create-index.html
The MyISAM, InnoDB, NDB, and ARCHIVE storage engines support spatial columns such as (POINT and GEOMETRY. (Section 11.17, “Spatial Extensions”, describes the spatial data types.)
Spatial keys are:
•Available only for MyISAM tables. Specifying SPATIAL INDEX for other storage engines results in an error.
•Indexed columns must be NOT NULL.
•In MySQL 5.1, column prefix lengths are prohibited. The full width of each column is indexed.
Did you know that is a special https://gis.stackexchange.com/ forum for these kinds of questions,
I recommend you (double) post your question there as well.
As your inner SELECT
uses post_type
, lat
and lon
in WHERE
clause I would recommend to put an index on those.
Use EXPLAIN [QUERY]
to see if the index is used and what benefit you get from it.
精彩评论