我正在运行一个根据位置返回结果的 MySQL 查询。但是我最近注意到它确实减慢了我的 PHP 应用程序的速度。我使用了 CodeIgniter,探查器显示查询耗时 4.2 秒。 geoname 表有 500,000 行。我在键列上有一些索引,还有什么可以加快此查询的速度?
这是我的 SQL:
SELECT `products`.`product_name`
, `geoname`.`geonameid`
, `geoname`.`latitude`
, `geoname`.`longitude`
, `products`.`product_id`
, AVG(ratings.vote) as rating
, count(comments.comment_id) as total_comments
, (6371 * acos(cos(radians(38.7666667))
* cos(radians(geoname.latitude))
* cos(radians(geoname.longitude) - radians(-3.3833333))
+ sin(radians(38.7666667))
* sin(radians(geoname.latitude)))
) AS distance
FROM (`foods`)
JOIN `geoname` ON `geoname`.`geonameid` = `products`.`geoname_id`
LEFT JOIN `ratings`
ON `ratings`.`var_id` = `products`.`product_id`
LEFT JOIN `comments`
ON `comments`.`var_id` = `products `.`product_id`
WHERE `products`.`product_id` != 82
GROUP BY `products`.`product_id`
HAVING `distance` < 99
ORDER BY `distance`
LIMIT 10
最佳答案
让我们从查询本身开始 cos(radians(geoname.latitude)) 和其他函数看起来像一个不变量,所以我们可以做一些预处理并将计算值存储在表中。 (计算三角函数主要涉及使用代价高昂的级数展开)。
6371 * acos(cos(radians(38.7666667)) - 这等于 radians(38.76667) * 6371 那么为什么要我们呢?它的成本。
其次,如果您不太关心精度,您可以预先计算弧度本身,比方说从 0 到 pi/2 的 10000 个点 - 这应该给出一个很好的近似值,最多 4 个小数,例如小于 km
(6371 * acos(cos(radians(38.7666667))
* cos(radians(geoname.latitude))
* cos(radians(geoname.longitude) - radians(-3.3833333))
+ sin(radians(38.7666667))
* sin(radians(geoname.latitude))))
还记得 sin(a) 当 a > pi/2 且 a < pi 等于 sin(pi - a) 当 a> pi 且 a < 3/2 pi 等于 -sin(a-pi) 并且当 a > 3/2 pi 且 a < 2pi 时等于 -sin (2pi - a)。可以为 cos 函数创建类似的函数。
试试看是否有帮助。 卢克
关于sql - 优化 SQL 距离查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2441757/