sql - 如何优化 SQL 查询地理定位数据?
问题描述
我们的任务是在客户指定的位置找到房产。我们有一个 MySQL 表,其中包含属性的经度和纬度。
地址经度纬度
地址 1 42.4001742 -71.1213472
地址 2 42.4651592 -71.01366
因此,从逻辑上讲,我们可以根据客户端位置进行 SQL 搜索
Select * from addresses where longitude between (client.location. longitude + 0.1)
and (client.location. longitude - 0.1) and latitude between
(client.location. latitude + 0.1) and (client.location. latitude - 0.1)
如果有成千上万的房产,这种搜索的效果如何?优化此搜索的可能方法是什么?
解决方案
您将需要此索引(使用 BTREE 索引)。
CREATE INDEX latlon ON addresses (latitude, longitude);
您的查询将对纬度(南北方向)进行索引范围扫描,然后在东西方向上进行过滤。这是相当有效的。
一个纬度(南北)是 69 英里或 111.111 公里(根据拿破仑对米的定义……从赤道到极地的一千万米)。
每经度的距离(西-东)根据您与赤道的距离而有所不同。离赤道越远,距离越短。在美国马萨诸塞州萨默维尔,一个经度度约为 51 英里。(你确实通过你的例子告诉我们你在哪里。)
因此,如果您想要一个以 (42.4002 -71.1213) 为中心的每个方向三英里的边界框,您需要这个过滤子句。
WHERE latitude BETWEEN 42.4002 - (3.0/69.0)
AND 42.4002 + (3.0/69.0)
AND longitude BETWEEN -71.1213 - (3.0/(69.0 * COS(RADIANS(42.4002))))
AND -71.1213 + (3.0/(69.0 * COS(RADIANS(42.4002))))
如果您想以公里为单位提供您的盒子,请使用 111.111 代替 69.0。如果您想要一个不同大小的盒子,请使用不同的数字代替 3.0。
该过滤器表达式使用我提到的索引就好了。
如果表中的所有位置主要分布在东西方向而不是南北方向(例如,沿着马萨诸塞州收费公路),则切换索引中两列的顺序以获得更好的选择性。但通常这并不重要。
CREATE INDEX lonlat ON addresses (longitude, latitude);
您可能会发现阅读此内容很有帮助。
专业提示最好在海洋或玉米地中给出纬度/经度示例。
推荐阅读
- r - 识别连续值变化的类型 - R
- powershell - 已解决:使用 Powershell 5+ 注册计划任务时,无法将“smaThrottlingJob”... 转换为“mmiCimInstance”的原因是什么?
- sql - 如何编写 SQL 查询以在一行中获取一个 ID 的多个值?
- google-bigquery - BigQuery 递归计算列
- canvas - 删除画布媒体流中的黑色背景
- java - 如何从多个工作表中获取列值
- javascript - JavaScript 正则表达式不会在逗号或制表符空间上拆分
- c# - 文本框方法
- python - Django从媒体文件而不是数据库显示图像
- sql - 能不能用函数参数调用sqlplus