开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜