gpt4 book ai didi

mysql - 我可以避免在此查询中重复计算吗?

转载 作者:行者123 更新时间:2023-11-29 07:50:11 27 4
gpt4 key购买 nike

要匹配靠近纬度和经度点的点(point_lat, point_lon)我需要做这样的事情,

SELECT id, lat, lon,
ACOS(COS(RADIANS(ABS(lat - point_lat))) * COS(RADIANS(IF(ABS(lon - point_lon) > 180, 360 - ABS(lon - point_lon), ABS(lon - point_lon))))) as angle_between
FROM places;

查询的 IF(ABS(lon - point_lon) > 180, 360 - ABS(lon - point_lon), ABS(lon - point_lon)) 部分真的很伤我的眼睛,看起来像 ABS(lon - point_lon) 计算了 2 次,除非 MySQL 内部优化了 IF

places 表非常大(约 600 万行),因此我希望尽可能高效地完成此操作。您有什么建议吗?

编辑: ABS(lon - point_lon) 计算起来并不昂贵,我知道。但事实上,我在查询中选择的 angle_ Between 需要类似于 angle_ Between = IF(angle_ Between > 180, 360 - angle_ Between,angle_ Between) 并且angle_ Between的计算是相当昂贵的。

我知道我可以使用派生表,查询变为:

SELECT t.id, t.lat, t.lon, t.angle_between, if(t.angle_between > 180, 360 - angle_between, angle_between) as angle FROM (
SELECT id, lat, lon,
ACOS(COS(RADIANS(ABS(lat - point_lat))) * COS(RADIANS(IF(ABS(lon - point_lon) > 180, 360 - ABS(lon - point_lon), ABS(lon - point_lon))))) as angle_between
FROM places
) AS t
ORDER BY angle LIMIT 20;

“自定义 MySQL 函数”似乎也是一种选择,但我不太确定它们的性能。

最佳答案

我不会担心计算 ABS(lon - point_lon) 所花费的时间。这应该是计算的一小部分,特别是在使用三角函数时。事实上,对于大多数查询来说,访问数据所花费的时间在查询中占主导地位;不是运行函数所花费的时间。情况并非总是如此,但在您的查询中,ACOS() 和其他函数将花费更多时间。

如果您不想要显式的 if(),您还可以使用:

greatest(ABS(lon - point_lon), 360 - ABS(lon - point_lon))

编辑:

在您的特定情况下,您可以这样做:

IF( (@x := ABS(lon - point_lon)) > 180, 360 - @x, @x)

这只能保证有效,因为所有逻辑都在一个语句中(这就是为什么我没有首先提出它)。 MySQL 不保证 select 子句中表达式求值的顺序,因此您不应在任何其他表达式中使用 @x

其他选项,例如使用子查询或union all,需要读取和写入更多数据。这是性能提升的一个很高的阈值(您始终可以测试替代方案,看看它们是否效果更好,只是不要太乐观)。换句话说,尽管变量方法可能最适合您的特定情况,但没有真正好的解决方案。

关于mysql - 我可以避免在此查询中重复计算吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26671907/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com