我有一个系统会从数据库中返回所有用户,并按照与引用邮政编码的最短距离对结果进行排序。
例如:用户将访问网站,输入邮政编码,它将返回距离他的邮政编码最近的所有其他用户(升序)
我现在是怎么做到的,为什么会出现问题?
该系统包含超过 3000 万用户及其邮政编码。我正在检索特定州和城市的所有用户(将数据集缩小到大约 10,000)。
这就是问题实际发生的地方。现在,mysql (10,000) 行发送到 PHP 的所有结果都被发送到一个邮政编码计算器库,该库计算基本邮政编码和用户邮政编码之间的距离 - 10,000 次。然后按最近的邮政编码对结果进行排序。
如您所见,这是一段非常糟糕的优化代码。并且 10,000 条记录循环了两次。更不用说每个 httpd 进程仅在 mysql 之间传输数据所占用的 RAM 量。
请问这里的大神有什么办法可以优化吗?
我有一些自己的想法,但我不确定它们的效率如何。
尝试在 mysql 本身中进行所有邮政编码计算和排序,并返回分页的行数。 为此,我需要将邮政编码计算逻辑之间的距离移至存储过程。这样我就可以防止在 PHP 中处理 10,000 条记录。但是,仍然存在问题。我不需要计算已经计算的邮政编码的距离(对于具有相同邮政编码的 2 个用户)。
其次,如何使用存储过程对 mysql 中的行进行排序?
大家怎么看?这是一个好方法吗?我可以期望使用它来提高性能吗? 您还有其他建议吗?
我知道这个问题很大,非常感谢您花时间阅读到最后。我真的很想听听您对此的看法。
最佳答案
由于我对 PHP 或 MySQL 不是很熟悉,所以我只能提供一些基本技巧,但它们应该有所帮助。这还假设您没有直接的方式与 MySQL 中的 zip 库进行交互。
首先,由于怀疑您在一个城市中是否有 10k 邮政编码,请使用您现有的查询并执行类似的操作
SELECT DISTINCT ZipCode FROM Users WHERE ...
这可能会返回最多几十个邮政编码,并且不会重复。通过您的邮政编码库运行它。该库本身可能是速度缓慢的根源,因为它必须查找邮政编码,并进行一系列花式触发以获得实际距离。获取此结果,并将其插入到仅包含邮政编码和距离的临时表中。
完成该列表后,进行另一个查询以获取您想要的其余用户数据,然后加入邮政编码的临时表以获取您的距离。
这应该会给您带来相当大的加速。在计算出结果后,您可以在第二个查询中执行任何需要的分页。不再循环遍历 10k 行。
关于php - 按邮政编码距离升序计算和排序用户的最快方法(也是最优化的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5213475/