使用或不使用反向地理编码来索引约 500,000 行的 MySQL 表?
Posted
技术标签:
【中文标题】使用或不使用反向地理编码来索引约 500,000 行的 MySQL 表?【英文标题】:To use or not to use inverse geocoding to index a MySQL table with ~500,000 rows? 【发布时间】:2013-02-06 21:58:48 【问题描述】:我有一个包含大约 5,000 行的表,其中包含地标上的地理坐标(纬度+经度)和位置信息(城市、州和国家/地区)。我使用此表来检索离用户位置最近的位置(例如附近的公园等)。
目前,我通过对用户的 gps 坐标进行反向编码来过滤查询,以获取他的城市、州和国家(我正在使用 android 的地理编码器)。但是,我开始意识到 Geocoder 有时会失败,因此我的云服务器上的 SQL 查询不会返回任何结果。
所以我正在考虑跳过反向编码以确保每次都能获得良好的结果。我将使用地理坐标来获得我想要的,如下所示:
SELECT p.placeId, p.name,( 6371 * acos( cos( radians($latitude) ) * cos( radians( p.latitude ) ) * cos( radians( p.longitude ) - radians($user_longitude) ) + sin( radians($user_latitude) ) * sin( radians( p.latitude ) ) ) ) AS distance ORDER BY distance
但是,我的桌子每天都在增加,最终可能会增长到 500,000。您是否认为当我的表扩展到该大小时,对每一行执行距离计算可能会成为性能问题?还是 500,000 行的表真的不是问题?
【问题讨论】:
如果它成为问题,您可以使用 WHERE 子句限制查询,该子句仅选择 (Lat-X,Lon-X):(Lat+X,Lon+X) 内的记录X 是您首先要搜索多远的粗略预定值。例如,当您在加利福尼亚时,按佛罗里达的距离加油站计算和订购没有多大意义 【参考方案1】:您可以将搜索范围限制为所需的记录范围和数量。在本例中为 25 公里和 20 条记录。
SELECT placeId, name, lat, lng,
( 3959 * acos( cos( radians($user_latitude) ) * cos( radians( lat ) )
* cos( radians( lng ) - radians($user_longitude)) + sin( radians($user_latitude))
* sin( radians( lat ) ) ) ) AS distance FROM myTable HAVING distance < 25
ORDER BY distance LIMIT 0 , 20
在 500,000 行 mysql 数据库上运行此查询耗时 2.08 秒。
建议在准备好的语句中使用PDO
【讨论】:
【参考方案2】:是的。您可以使用空间索引。例如,Mssql 使用空间填充曲线。曲线减少了维度,不会与自身相交并保留一些原始的位置信息。曲线常用于制图应用。在 nick 的空间四叉树希尔伯特曲线博客中了解它。我写了一个希尔伯特曲线搜索 lat lng 对,它非常快。您可以使用包含 4 个字母的字符串来代替数字来索引位置。然后您可以从左到右搜索字符串中的位置。当然,您可以将索引反转为 lat-lng 并返回。
【讨论】:
以上是关于使用或不使用反向地理编码来索引约 500,000 行的 MySQL 表?的主要内容,如果未能解决你的问题,请参考以下文章