Php mysql内部连接导致服务器崩溃
我有两张桌子,机场和跑道Php mysql内部连接导致服务器崩溃,php,mysql,database,inner-join,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. | 2
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=“选择不同的*,
(3959*acos(cos(radians(47))*cos(radians(`airports`.latitude_度))*cos(radians(`airports`.经度)-radians(11))+sin(radians(47))*sin(radians(`airports`.latitude_度)))作为距离
从距离的“机场”开始是的,这个查询会像糖蜜一样慢。它必须计算整个数据库中每一个可能的机场组合的距离,以便计算出哪些机场的距离小于70,然后将结果减少到10个条目。这将是绝对的对数据库进行简单的搜索,再多的表索引也无济于事
您需要找到一种方法来避免在WHERE
或HAVING
子句中使用计算距离字段
可能最容易做到这一点的方法是作弊。创建一个表,其中包含每个机场之间的所有计算距离,并进行查询。这些距离不会改变,因此不必在每次有人查看您的站点时重新计算它们是有意义的
您需要在某个时刻对每个组合进行计算,但您只需进行一次,而不必在用户等待页面加载时进行
是的,这种方法会增加数据库所需的存储空间,但回报是它会使您的查询速度极快
如果您想使其更快,还可以使用原始lat/long字段限制正在联接的记录。如果您希望半径为70英里,我们知道lat和long与源的差异都不能超过70英里,因此您可以将它们添加为筛选器;这意味着您可以将查询筛选到140倍以内的记录在我们开始查看实际计算的距离之前,这将大大减少您的查询必须搜索的记录数,并将加快速度,即使使用预先计算的距离表也是如此。您从服务器得到了什么崩溃错误?它没有响应!可能是由于庞大的数据库。我必须每次都重新启动整个系统。你检查服务器的日志了吗?是的,没有条目!-至少我没有访问权限。查询在你看来如何?having
子句破坏了一切,因为它知道给定记录是否有距离的唯一方法是,即使你不去,也可以使用我最后一段中的建议使用缓存计算的思想。将long和lat限制在一个有限的范围内,作为一组附加的具有
或where
子句,这样就不必进行太多的计算来确定是否应该包括一条记录,因为只需查看静态long/lat,它就可以忽略大多数记录价值观
$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";