4

大規模なOracleデータベース(約720,000レコード)があり、各レコードには独自の地理座標(lat&lng)があり、ポイントから特定の距離(特定の半径内)にあるレコードのみを選択する必要があります。

現在、オラクルフォーラムで見つけた距離関数(haversineに基づく)を実装しましたが、データベースが少し大きいため、選択ごとに約50秒かかります。

これを効率的に行う方法に関する推奨事項はありますか?oracle Spatial&Locatorという拡張機能があることは知っていますが、それを購入できるかどうか、さらにはどのように機能するかさえわかりません。よろしくお願いします。よろしくお願いします

4

8 に答える 8

5

Lat値とLong値の特定の形式、およびハバーシンの実装に使用される特定の式についての詳細を提供してください。

物事をスピードアップできる3つのアプローチがあります。状況に応じて、これらのうち少なくとも2つを実行できます。

  1. 単純な属性値の比較により、可能な限り多くのレコードを削除します。
    これらのレコードについては、何も計算する必要はありません。
    たとえば、最大半径の要件を、経度(および場合によっては緯度)の値の[寛大であるがおおよその]範囲に変換します。

  2. 代替の(おそらく近似の)距離測定を使用します。
    たとえば、切り上げられた座標に基づいて、ユークルディディアン距離の2乗を計算する方が速い場合があります。(そしてもちろん、これを目的の半径の2乗と比較します)

  3. 半正矢関数の実装方法を改善します

于 2009-10-19T22:08:44.987 に答える
5

より良いアルゴリズムを使用してください。平方根の計算が必要な実際のユークリッド距離を計算する代わりに、減算と加算のみが必要な直線距離を選択します。つまり、ポイントが (10, 10) にあり、半径が 5 の場合、(10 +/- 5, 10 +/- 5) で形成される正方形内にポイントがあるすべての場所を選択します。

これにより、正方形の隅にある少数の誤検知が検出されます。適切なユークリッド距離を計算してアプリケーションの結果を再確認することで、これらを排除します。

于 2009-10-19T21:57:45.800 に答える
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を参照してください

2 つ目 - PL/SQL は、何度も呼び出される多数のコード行を含む計算をプログラムするための完璧なツールではありません。Java または C++ で数学を実装すると、パフォーマンスが大幅に向上します。C++ または Java コードは、関数のように Oracle から呼び出すことができます。

第三に、単純な長方形のボクシングでできるだけ多くのポイントを切り取る必要があるとコメントした人は非常に正しいです。経度と緯度の列でインデックスを作成すると、そのボクシング句を実行するのに役立ちます。

最後に、Oracle Spatial がここに関与する必要はないと思います。やり過ぎです。すでに持っていて SDO_GEOMETRY 列を作成した場合、これは 1 つの話ですが、そうでない場合は考慮しません。

于 2012-10-08T12:40:14.713 に答える