从 Postcode DB 获取 lat/lng 并在 PHP/MYSQL 中按最近的顺序排序
Posted
技术标签:
【中文标题】从 Postcode DB 获取 lat/lng 并在 PHP/MYSQL 中按最近的顺序排序【英文标题】:Get lat/lng from Postcode DB and order by nearest first in PHP/MYSQL 【发布时间】:2016-01-10 22:03:48 【问题描述】:我正在尝试首先按最近的位置对搜索结果进行排序。我有一个项目表和一个交易表。我需要在这两个表中搜索项目/交易位置,然后将位置与我的邮政编码数据库进行比较,并从相应的数据库条目中获取纬度和经度并对结果进行排序。我正在使用 PDO 准备好的语句。
我的数据库中有 3 个表。邮政编码、优惠和商品。
邮政编码
| postcode | lat | lng |
交易
| id | title | location |
物品
| id | title | location |
这是我的 SQL...
SELECT SQL_CALC_FOUND_ROWS *
FROM (
SELECT *
FROM items
UNION
SELECT * FROM deals
) AS allitemsdeals
INNER JOIN (
SELECT
postcodes.*,
(3959 * acos(cos(radians(custom.lat)) * cos(radians(postcodes.lat)) * cos(radians(custom.lng) - radians(postcodes.lng)) + sin(radians(custom.lat)) * sin(radians(postcodes.lat)))
) AS distance
FROM postcodes
INNER JOIN postcodes AS custom
WHERE custom.postcode = ?
) postcodes ON allitemsdeals.location = postcodes.postcode
HAVING distance < 5 ORDER BY id LIMIT ? OFFSET ?
我的加入有问题。查询有效,但大约需要一分钟! :(
任何帮助将不胜感激!谢谢! :)
【问题讨论】:
ST_Within 可能会加快速度,但如果不查看您的解释输出,则只能猜测。请更新您的问题,而不是发布 PHP,而是发布实际执行的 sql 查询。并指出您的表格是什么样的以及它们的行数是多少 感谢您的回复。该问题已通过示例进行了更新。 :) 仍然需要解释输出。 【参考方案1】:子查询正在扼杀您的性能。尝试在 SELECT
上添加 EXPLAIN
并查看输出 - 我怀疑有很多 USING FILESORT
和 USING (NULL) INDEX
的东西。并且检查了很多记录。可能还有一些derived
表...
所有这些JOIN (SELECT ...
语句都会导致查询运行,结果被缓存(或者更糟糕的是,仍然为JOIN
左侧的每条记录重新运行)而没有任何索引 - 一切都变得可怕停下来。
最后SQL_CALC_FOUND_ROWS
- 如果你不需要,就不要这样做。它会导致 MySQL 在应用 LIMIT
之前计算所有行并处理所有行以计算它们。即使在LIMIT
之前,您最好尽可能地减少结果 - 而且绝对最好不要使用SQL_CALC_FOUND_ROWS
。 (相信我,单独的SELECT COUNT(1)
会更好。去过那里。)
解决方案?不容易。首先更改您的架构。
首先:我会将“交易”和“项目”合并到一个大表中 - 使用一列来区分类型(除非还有很多其他列我没有看到) 因为UNION
可能(或肯定?)会杀死您拥有的任何索引。
第二个:距离的子查询 - 哦不!那应该是用于计算最大距离的直接WHERE
子句。如果您愿意,我会尝试对其进行优化 - 但如果没有 SQLfiddle.com 或其他可玩的东西,在我的空闲时间开始复制您的架构和数据有点多。 (如果你用它设置一个 SQLfiddle - 我会很高兴地戳一下。)
第三:我会考虑使用 MySQL 的空间功能从 long/lat 数据重新开始。有很多可用的文档:
https://www.percona.com/blog/2013/10/21/using-the-new-spatial-functions-in-mysql-5-6-for-geo-enabled-applications/ Fastest Way to Find Distance Between Two Lat/Long Points ...等这是一些很酷的东西 - 很长一段时间以来,我一直想找个借口在(付费!)几个小时内使用这些数据。我很想看看你最终会得到什么解决方案。
正如我所说 - 如果您提供 SQLfiddle(假设其他人没有首先提供更好的解决方案),至少我会很乐意在接下来的 72 小时内查看一下。
【讨论】:
好答案。但我认为您链接到的“最快找到...”中的大多数答案已被 st_within 取代 找到最近的 5 个的“最快”方法不能使用简单的索引——您会被全表扫描或一维扫描(例如lat between ... and ...
)卡住。如需在任意大型数据集中快速查找,请参阅mysql.rjweb.org/doc.php/latlng。以上是关于从 Postcode DB 获取 lat/lng 并在 PHP/MYSQL 中按最近的顺序排序的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Google Maps V3 从 lat/lng 获取城市?
如何从位置(x,y)获取 google maps v3 上的位置(lat/lng)