緯度/経度座標を格納しているテーブルがあり、特定のポイントの距離内にあるすべてのレコードを取得するクエリを作成したいと考えています。
このテーブルには約 1,000 万件のレコードがあり、Lat/Long フィールドのインデックスがあります
これは正確である必要はありません。とりわけ、経度 1 度 == 緯度 1 度であると考えていますが、これは正しくありませんが、取得している楕円はこの目的には十分です。
以下の例では、問題の点が [40, 140] で、半径 (度) が 2 度であるとします。
私はこれを2つの方法で試しました:
1) 2 点間の距離の平方を計算する UDF を作成し、その UDF をクエリで実行しています。
SELECT Lat, Long FROM Table
WHERE (Lat BETWEEN 38 AND 42)
AND (Long BETWEEN 138 AND 142)
AND dbo.SquareDistance(Lat, Long, 40, 140) < 4
最初に正方形でフィルタリングして、クエリを高速化し、SQL でインデックスを使用できるようにしてから、円内にあるレコードのみが UDF と一致するように調整します。
2)クエリを実行して平方を取得し(前と同じですが、最後の行はありません)、これらのすべてのレコードを ASP.Net コードにフィードし、ASP.Net 側で円を計算します(同じ考え、平方を計算しますSqrt 呼び出しを保存する距離、および半径の 2 乗と比較します)。
驚いたことに、.Net 側での円の計算は、UDF を使用するよりも約 10 倍高速であり、その UDF で何かひどく間違ったことをしていると思います...
これは私が使用しているコードです:
CREATE FUNCTION [dbo].[SquareDistance]
(@Lat1 float, @Long1 float, @Lat2 float, @Long2 float)
RETURNS float
AS
BEGIN
-- Declare the return variable here
DECLARE @Result float
DECLARE @LatDiff float, @LongDiff float
SELECT @LatDiff = @Lat1 - @Lat2
SELECT @LongDiff = @Long1 - @Long2
SELECT @Result = (@LatDiff * @LatDiff) + (@LongDiff * @LongDiff)
-- Return the result of the function
RETURN @Result
END
ここで何か不足していますか?
SQL Server 内で UDF を使用することは、.Net に必要以上に約 25% 多いレコードを供給するよりもはるかに高速であるべきではないでしょうか? DataReader のオーバーヘッド、プロセス間の通信などでしょうか?
そのUDFで実行速度が遅くなるような、ひどく間違っていることはありますか?
それを改善する方法はありますか?
どうもありがとうございました!