2012-06-28 46 views
0

对不起,如果这已经回答了(我确定有人会扔我的链接,如果有的话)。我回想起一个类似的问题,但我现在找不到它。基于距离的优化用户数据库搜索

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

  • 执行必需的数学来确定边界框,然后查询拉链表以找到那些潜在的候选人,然后用任何的那些邮政编码搜索用户的所有邮政编码?

OR

  • 确定纬度/经度边框,与用户表连接的zip表并与用户谁的纬度/多头参数之间掉下返回结果?

我想第二种方法会更快,但我没有支持证据/具体经验,这表明它会。我知道有足够的SQL来解决问题,但我仍然对它有所了解,并且在涉及到不同类型操作的相对性能时并不知情。

谢谢你的时间!

回答

2

我相信你最终的查询应该是这样的:

-- 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 

所以在这种情况下很,我不为一切一气呵成情况了解您的疑虑。查询优化器通常比任何首先要执行的人都知道得更好。

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

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

+0

谢谢。这个问题可能表达得很差,实际上是询问是否执行两个单独的查询(一个是获取一个邮政编码数组,然后是另一个邮政编码,以查看哪个用户与该列表中的邮编匹配),或者执行联合(非常精确如上所示)。也许愚蠢的问题,我只是不知道连接速度是如何比较两个单独的查询(没有连接)。这是我将继续前进的路线。感谢您花时间。 (以及其他所有人) – dgeare

+0

@dgeare如果您要使用与我建议的查询相似的查询,那么您应该在'location(id,纬度,经度)'上放置一个索引。这样,MySQL就能够仅处理索引,并且通常可以从内存中进行处理。它往往(如果不是总是)比将拉链代码列表(到应用程序层?)更快,然后用这些结果运行第二个查询。至少你避免了两层之间的通信(假设有多层设置,例如PHP + MySQL)。 – RandomSeed

+0

邮政编码表目前使用邮政编码(varchar(5))作为PK,与users表中的外键字段对应。你是否建议在zip表中使用数字代理键会加速连接,或者当前的设置是否足够?谢谢。 – dgeare

1

你描述可以这样概略地说明这两种算法:

A INNER JOIN B WHERE A satisfies condition 

(A WHERE A satisfies condition) INNER JOIN B 

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

后者涉及子查询。您的描述似乎认为子查询是先计算的,然后是加入,但通常是not the case。内连接首先被评估,子查询第二,这可能会给你与第一种情况相同的执行计划。

因此,这两种方法似乎与性能角度不同,您应该专注于选择一种最易于阅读和维护的方法,并在当日来临时优化profile