mysql内连接使服务器崩溃

时间:2015-08-08 18:30:59

标签: php mysql database inner-join

我有两张桌子,机场和跑道。

airports:
id | ident | name              | latitude_deg | longitude_deg |
----------------------------------------------------------------
1  | KJFK  | JFK airport NYC   | 47.12345678  | 11.1234567    |
2  | KLAX  | Los Angeles Intl. | 20.12345678  | 9.12345678    |
...

runways:
id | airport_ident | le_ident | length
---------------------------------------
4  | KJFK          | 08/26    | 6000ft
5  | KJFK          | 20/02    | 3000ft
...

我使用以下查询获取70英里范围内的所有机场(工作正常):

$output  = "SELECT distinct *, 
( 3959 * acos( cos( radians( 47 ) ) * cos( radians( `airports`.latitude_deg ) ) * cos( radians( `airports`.longitude_deg ) - radians( 11 ) ) + sin( radians( 47 ) ) * sin( radians( `airports`.latitude_deg ) ) ) ) AS distance
FROM `airports` HAVING distance <= 70
ORDER BY distance LIMIT 10";

当我想加入这两个表时,如何扩展查询? 我试过了:

$output  = "SELECT distinct *, 
( 3959 * acos( cos( radians( 47 ) ) * cos( radians( `airports`.latitude_deg ) ) * cos( radians( `airports`.longitude_deg ) - radians( 11 ) ) + sin( radians( 47 ) ) * sin( radians( `airports`.latitude_deg ) ) ) ) AS distance
FROM `airports` INNER JOIN `runways` ON `airports`.ident = `runways`.airport_ident HAVING distance <= 70
ORDER BY distance LIMIT 10";

但这会导致我的服务器崩溃。

有什么想法吗?谢谢!

1 个答案:

答案 0 :(得分:0)

是的,该查询将与糖蜜一样慢。它必须计算整个数据库中每个可能的机场组合的距离,以便确定哪些机场的距离小于70,然后将结果减少到10个条目。它绝对会破坏数据库,并且没有任何表索引可以提供帮助。

您需要找到一种避免在WHEREHAVING条款中使用计算出的距离字段的方法。

你可以轻松实现这一目标的最简单方法就是作弊。创建一个包含每个机场之间所有计算距离的表,并查询该表。距离不会改变,因此每次有人查看您的网站时都不必重新计算它们。

您需要在某个时刻对每个组合进行计算,但您只需要执行一次,并且在用户等待页面时不必进行此操作负荷。

是的,这种方法会增加您的数据库所需的存储空间,但奖励是它会使您的查询闪电般快速。

如果你想让它更快,那么使用原始lat / long字段限制连接的记录也会很有帮助。如果你想要一个70英里的半径,我们知道纬度和长度都不能超过距离源70英里,所以你可以添加它们作为过滤器;这意味着在我们开始查看实际计算的距离之前,您可以将查询过滤到140x140英里的正方形内的记录。这应该会大大减少您的查询必须搜索的记录数量,并且即使使用预先计算的距离表,也应该加快速度。