
在地理信息系统或位置服务中,经常需要查询某个特定点附近的其他点,并按照距离远近进行排序。当处理相对较小的地理范围时,可以使用勾股定理(或其变形)来近似计算两点之间的平面距离。本文将围绕这一需求,介绍在postgresql中实现此类查询的两种有效方法,并分析其优缺点。
首先,我们来理解核心的距离计算表达式: ((abs(l.lat*111139 - myPointLat*111139)^2) + (abs(l.lng*111139 - (myPointLng*111139))^2))
这个表达式是计算两个点 (l.lat, l.lng) 和 (myPointLat, myPointLng) 之间距离的平方。
我们的目标是找到距离参考点 (myPointLat, myPointLng) 在 metres 范围内的点,并按距离升序排列。即满足 距离平方 <= metres^2 的条件,并按 距离平方 排序。
当距离计算表达式比较复杂时,为了提高SQL查询的可读性和维护性,可以将距离计算封装在一个子查询中,作为计算列。
SELECT Column1, Column2, Column3 -- 选择你需要的列
FROM
(
SELECT *, -- 或者只选择你需要的原始列
(
(ABS(l.lat*111139 - myPointLat*111139)^2) +
(ABS(l.lng*111139 - (myPointLng*111139))^2)
) AS proximity -- 将距离平方计算为一个名为 proximity 的新列
FROM point l
) AS subquery_points
WHERE proximity <= metres^2 -- 在子查询外部使用计算列进行过滤
ORDER BY proximity; -- 在子查询外部使用计算列进行排序在上述代码中:
为了最大化查询性能,尤其是在大数据集中,通常建议在 WHERE 和 ORDER BY 子句中直接重复距离计算表达式。
SELECT * -- 选择你需要的列
FROM point l
WHERE (
(ABS(l.lat*111139 - myPointLat*111139)^2) +
(ABS(l.lng*111139 - (myPointLng*111139))^2)
) <= metres^2 -- 在 WHERE 子句中直接使用距离平方表达式进行过滤
ORDER BY (
(ABS(l.lat*111139 - myPointLat*111139)^2) +
(ABS(l.lng*111139 - (myPointLng*111139))^2)
); -- 在 ORDER BY 子句中再次使用距离平方表达式进行排序在选择上述两种方法时,应根据具体场景权衡可读性、可维护性和性能。
在PostgreSQL中实现基于勾股定理的邻近点查询并按距离排序,可以通过子查询或重复表达式两种方式实现。子查询提供了更好的代码可读性,但可能牺牲部分性能;而重复表达式则能更好地利用数据库优化器的能力,实现更快的查询速度。在实际应用中,建议根据数据量、性能要求和代码维护成本综合考虑,并结合实际数据进行性能测试,以选择最适合的方案。对于专业的地理空间应用,PostGIS无疑是更优的选择。
以上就是PostgreSQL中基于勾股定理的邻近点查询与排序优化的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号