按邮政编码距离升序计算和排序用户的最快方式(也是最优化的)
Posted
技术标签:
【中文标题】按邮政编码距离升序计算和排序用户的最快方式(也是最优化的)【英文标题】:Fastest way (and most optimized) to calculate and sort users by ascending order of zip code distance 【发布时间】:2011-03-06 21:19:40 【问题描述】:我有一个系统,它将从数据库中返回所有用户,并按照与参考邮政编码的最短距离对结果进行排序。
例如:用户将来到网站,输入邮政编码,它将返回最接近他的邮政编码的所有其他用户(升序)
我现在怎么做?为什么会出现问题?
该系统包含超过 3000 万用户及其邮政编码。我正在检索特定州和城市的所有用户(将数据集缩小到大约 10,000 个)。
这就是问题实际发生的地方。现在,mysql (10,000) 行发送到 php 的所有结果都被发送到邮政编码计算器库,该库计算基本邮政编码和用户邮政编码之间的距离 - 10,000 次。然后按最近的邮政编码对结果进行排序。
如您所见,这是非常糟糕的优化代码。并且这 10,000 条记录循环了两次。更不用说每个 httpd 进程仅在 mysql 之间传输数据所需的 RAM 量。
我想问这里的大师,无论如何优化这个?
我有一些自己的想法,但我不确定它们的效率如何。
尝试在mysql本身中进行所有邮政编码的计算和排序,并返回分页的行数。 为此,我需要将邮政编码计算逻辑之间的距离移动到存储过程。这样我就可以防止在 PHP 中处理 10,000 条记录。但是,仍然存在一个问题。我不需要计算已经计算过的邮政编码的距离(对于具有相同邮政编码的 2 个用户)。
其次,如何使用存储过程对mysql中的行进行排序?
你们怎么看?这是一个好方法吗?我可以期待使用它来提升性能吗? 您还有其他建议吗?
我知道这个问题很大,我非常感谢您花时间阅读到最后。我真的很想听听您对此的看法。
【问题讨论】:
【参考方案1】:由于我对 PHP 或 MySQL 不太熟悉,我只能提供一些基本提示,但它们应该会有所帮助。这还假设您无法直接与 MySQL 中的 zip 库进行交互。
首先,由于您在一个城市中有 10k 个邮政编码是值得怀疑的,因此请使用您现有的查询并执行类似的操作
SELECT DISTINCT ZipCode FROM Users WHERE ...
这可能最多返回几十个邮政编码,并且没有重复。通过您的邮政编码库运行它。该库本身可能是缓慢的原因,因为它必须查找邮政编码,并进行一系列花哨的触发才能获得实际距离。获取此结果,并将其插入到临时表中,其中仅包含邮政编码和距离。
完成该列表后,进行另一个查询以获取您想要的其余用户数据,然后加入邮政编码的临时表中以获取您的距离。
这应该会给您带来相当大的加速。在计算结果后,您可以在第二个查询中执行您需要的任何分页。并且不再循环遍历 10k 行。
【讨论】:
【参考方案2】:我建议您在计算准确距离以进行过滤和排序之前缩小纬度和经度范围。
我的意思是,如果您进行全表扫描并计算数据库中所有邮政编码相对于您的参考点的距离,这将非常慢。
而是按邻近度过滤邮政编码。我的意思是如果你有纬度 10 和经度 20,首先计算你想要的接近度的最大角度范围。假设您想要 10 英里的接近范围。这可能转化为 0.15 度。因此,您需要首先过滤邮政编码,纬度在 10-0.15 和 10+0.15 之间,经度在 20-0.15 和 20+0.15 之间。
只有在那之后,您才能在 SQL 查询条件中包含准确的距离子句。这会快得多,因为您不再进行全扫描,并且您最终可以在经度和纬度字段上使用范围索引。
要将英里转换为度,请找到狭窄的范围,请记住,地球的周长约为 25,000 英里,将 25000 除以 360 度,即每度 70 英里。如果您想要 10 英里的射程,那么您的射程(度数)最多为 0.15 度。
请记住,这些计算并不准确(地球并不是完全圆整的),但这并不重要。重要的是,您要找到比真正准确值更高的度数范围值。
【讨论】:
【参考方案3】:如果您可以将所有邮政编码的纬度和经度获取到 MySQL 中,或者有一种简单的方法可以获取基本邮政编码的纬度/经度并将其输入到 MySQL 查询中,那么您可以按内部距离对 10k 用户进行排序mysql。有一个very similar question and answer here 可以为您提供距离函数的正确数学计算。您可能还想调查Mysql spatial extensions,它可以让您将纬度/经度插入并索引为 2D POINT 数据。
【讨论】:
我已经有一个邮政编码表,其中包含美国的每个邮政编码及其各自的纬度/经度。这会有帮助吗?以上是关于按邮政编码距离升序计算和排序用户的最快方式(也是最优化的)的主要内容,如果未能解决你的问题,请参考以下文章
php 使用WP REST API计算纬度和经度坐标之间的距离,并返回按用户c的距离排序的帖子