【问题标题】:Optimized user database search based on distance基于距离的优化用户数据库搜索
【发布时间】:2012-06-28 20:38:55
【问题描述】:

很抱歉,如果这个问题已经得到回答(如果有的话,我相信有人会向我抛出链接)。前段时间想了一个类似的问题,但现在找不到了。

所以,对于这个问题:我正在为我正在开发的网站构建用户搜索,其中一个搜索条件将基于与搜索用户的距离。我已经有一张美国邮政编码及其对应的经纬度表。我还想出了如何确定边界框(最大纬度/最小纬度 - 最大长度/最小长度)以确定哪些拉链符合标准(我们不会担心精确的半径。地理正方形暂时够用了)。我的问题 - 我应该如何构建查询以优化速度?我应该:

  • 执行所需的数学运算以确定边界框,然后查询邮政编码表以查找所有潜在候选邮政编码,然后搜索具有这些邮政编码的用户?

  • 确定纬度/经度边界框,将 zip 表与用户表连接,并返回纬度/经度介于参数之间的用户的结果?

我想第二种方法会更快,但我没有支持证据/具体经验表明它会。我知道足够多的 SQL 来解决问题,但我对它还是有点陌生​​,并且对于不同类型操作的相对性能一无所知。

感谢您的宝贵时间!

【问题讨论】:

    标签: mysql database zipcode


    【解决方案1】:

    我相信您的最终查询应该如下所示:

    -- compute @minLat, @maxLat, @minLon, @maxLon
    
    SELECT users.*
    FROM users
    JOIN locations ON locations.id = users.location
    WHERE locations.latitude BETWEEN @minLat AND @maxLat
    AND locations.longitude BETWEEN @minLon AND @maxLon
    

    所以在这种情况下,我不理解您的担忧,因为一切都是一次性发生的。查询优化器通常比任何人都更清楚JOIN 首先执行哪个。

    如果您想实现更复杂的计算来确定邮政编码是否在范围内,那么我更愿意先建立一个邮政编码列表,然后匹配居住在这些地区的用户。

    这假设计算邮政编码是否在搜索范围内是操作中成本最高的部分。因此,我更喜欢使用尽可能小的数据集(即仅邮政编码,而不是邮政编码 + 用户)运行此计算。即使在这种情况下,查询优化器也可能会为您做出正确的选择。

    【讨论】:

    • 谢谢。这个问题可能措辞不当,实际上是在询问是否执行两个单独的查询(一个获取邮政编码数组,然后另一个查询与该列表中的邮政编码匹配的用户),还是执行连接(几乎完全准确如上所示)。也许是愚蠢的问题,我只是不知道连接与两个单独的查询(没有连接)相比有多慢。这是我要继续前进的路线。感谢您抽出宝贵时间。 (以及其他所有人)
    • @dgeare 如果您要使用类似于我建议的查询,那么您应该在location(id, latitude, longitude) 上放置一个索引。通过这种方式,MySQL 只能处理索引,并且通常来自内存。它通常(如果不是总是)比提取邮政编码列表(到应用程序层?)然后使用这些结果运行第二个查询更快。至少您避免了两层之间的通信(假设是多层设置,例如 PHP + MySQL)。
    • 邮编表目前设置为以邮编(varchar(5))为PK,对应users表中的一个外键字段。您是否建议 zip 表中的数字代理键可以加快连接速度,或者当前设置是否足够?谢谢。
    • @dgeare 不,我的意思是,上述查询将从ALTER TABLE locations ADD INDEX (latitude, longitude) 等多列索引中受益匪浅。前两列被一起索引,WHERE 子句只能对索引起作用。
    【解决方案2】:

    您描述的两种算法可以这样示意性地描述:

    A INNER JOIN B WHERE A satisfies condition
    

    (A WHERE A satisfies condition) INNER JOIN B
    

    前者只是一个联接(条件可以是联接条件或 WHERE 条件,但这与 INNER JOIN 和 MySQL 无关)。

    后者涉及子查询。您的描述似乎假设首先计算子查询,然后是连接,但这通常是not the case。首先评估内部连接,然后评估子查询,这很可能会为您提供与第一种情况相同的执行计划。

    所以这两种方法从性能的角度来看似乎没有什么不同,你应该专注于选择一种对你来说最容易阅读和维护的方法,当那一天到来时,profile 并对其进行优化.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-25
      • 2012-05-22
      • 2015-01-21
      • 2016-07-22
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多