从 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 【问题描述】:

我正在用 phpmysql 建立一个网站。

我正在尝试首先按最近的位置对搜索结果进行排序。我有一个项目表和一个交易表。我需要在这两个表中搜索项目/交易位置,然后将位置与我的邮政编码数据库进行比较,并从相应的数据库条目中获取纬度和经度并对结果进行排序。我正在使用 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 FILESORTUSING (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)

解码 lat lng 值

根据地址获取 lat,lng

如何将地理位置 lat lng 从函数传递到 React 中另一个函数的“ll”属性?

如果 lat/lng 为空,要在 lat/lng 数据库字段中添加啥?