4

我有一个大型 Oracle 数据库(大约有 720,000 条记录),其中每条记录都有自己的地理坐标(纬度和经度),我只需要选择距离某个点特定距离(特定半径内)的记录。

目前我已经实现了一个距离函数(基于 hasrsine),我在一个 oracle 论坛中找到了它,但是因为数据库有点大,每次选择大约需要 50 秒。

关于如何有效地做到这一点的任何建议?我知道有一个名为 oracle spatial & locator 的扩展,但我不知道我是否可以购买它,甚至不知道它是如何工作的。提前非常感谢。最好的祝福

4

8 回答 8

5

使用更好的算法。无需计算需要平方根计算的实际欧几里得距离,而是选择仅需要减法和加法的线性距离。即,如果您的点位于 (10, 10) 并且您的半径为 5,则选择所有点位于由 (10 +/- 5, 10 +/- 5) 形成的正方形内的所有位置。

这将在正方形的角落捕获少量误报。通过计算适当的欧几里得距离来仔细检查应用程序中的结果来消除这些。

于 2009-10-19T21:57:45.800 回答
5

请提供有关 Lat 和 Long 值的具体格式的更多详细信息,以及用于实现半正弦的具体公式。

有三种方法可以加快速度。根据情况,我们至少可以做其中的两个。

  1. 通过简单的属性值比较尽可能多地剔除记录
    对于这些记录,我们根本不需要计算任何东西。
    例如,将最大半径要求转换为符合条件的经度(可能还有纬度)值的 [大方但近似] 范围

  2. 使用替代(可能是近似的)距离测量
    例如,基于四舍五入的坐标计算欧几里得距离的平方可能会更快。(当然要将此与所需半径的平方进行比较)

  3. 改进haversine公式的实现方式

于 2009-10-19T22:08:44.987 回答
4

一些建议,如果你还没有这样做...

  1. 由于 Haversine 计算需要以弧度为单位的角度,因此如果您以度为单位存储纬度和经度,请添加几列并预先计算弧度等值。更一般地说,预先计算函数中可以用于公式的任何值并存储它们。

  2. 考虑使用更简单的函数来消除半径之外的点,仅对基于更简单函数的潜在匹配点运行 Haversine 函数。对于度数,您可以使用 SQRT( (69.1*dLat) 2 + (53*dLong) 2 ) ) 并使用一些软糖因子 (10%)。如果您需要比更简单的计算提供的更好的结果,请仅在与粗略近似值匹配的点上运行您的 Haversine 计算。

于 2009-10-19T22:01:11.130 回答
3

如果您有许可证,那么可能会使用 Oracle Spatial

Oracle 文档 - Oracle Spatial

我没有使用它,但快速浏览文档会指向函数SDO_WITHIN_DISTANCE

于 2009-10-20T07:44:22.177 回答
2

“特定距离”是否有点恒定?IE 您总是在搜索“1 英里内的所有点”还是半径会发生变化?

您希望在任何给定查询中返回的总记录的百分比是多少?10%?.10%?

如果您将始终具有相同的半径,请构建一个长度与半径相同的正方形网格。为每个人分配一个相邻方格的列表。每个点都会知道它所在的方格,从中可以得到所有相邻方格的列表。然后仅对这些正方形中的点运行计算。这类似于弹出的其他答案,但会更快,因为线性计算是在索引查找中近似的,而不是在每个点之间计算。

即使使用可变半径,您仍然可以使用上述方法,但您必须计算要包含多少“邻居”。仅当您希望从任何单个查询中获得总数的一小部分时,这些才是可行的。

于 2009-10-19T22:05:08.030 回答
1

如果您不需要距离太准确,您可以将地球视为平坦的。从这个讨论

以英里为单位的近似距离:

sqrt(x * x + y * y)

其中 x = 69.1 * (lat2 - lat1) 和 y = 53.0 * (lon2 - lon1)

我最近对 ​​mysql 做了一些优化(此处概述:www.mooreds.com/wordpress/archives/000547 [对不起,我每个帖子只有 1 个超链接])但不确定我经历的步骤中有多少适用于 Oracle . 有些肯定是(如果可能的话,使用边界框)。

于 2009-10-19T21:59:17.777 回答
0
Approximate distance in miles:

sqrt(x * x + y * y) 
where x = 69.1 * (lat2 - lat1) and y = 53.0 * (lon2 - lon1)

您可以获得更准确的结果...如果您更改 53.0 幻数...同时考虑纬度的变化。(随着您向两极移动,逐渐变小。)

有没有人有那个魔法魔法公式?

于 2010-11-10T17:21:05.513 回答
0

首先,Haversine 并不完美,因为地球不是一个完美的球体 - 阅读http://www.movable-type.co.uk/scripts/latlong-vincenty.html

其次 - PL/SQL 不是一个完美的工具来编写多行代码的计算程序,这些代码将被多次调用。如果您使用 Java 或 C++ 来实现您的数学,您将获得巨大的性能提升。可以像函数一样从 Oracle 调用 C++ 或 Java 代码。

第三 - 评论说你需要用简单的矩形拳击尽可能多的点的人是非常正确的。通过经度和纬度列创建索引,这将有助于执行该装箱子句。

最后,我认为这里不必涉及 Oracle Spatial - 这是一种矫枉过正的做法。如果您已经拥有它并创建了 SDO_GEOMETRY 列,这是一个故事,但如果没有 - 我不会考虑它。

于 2012-10-08T12:40:14.713 回答