Đây là câu hỏi đầu tiên của tôi ở đây, vì vậy hãy chịu đựng với tôi!
Tôi đang triển khai một mặt sau cho một ứng dụng di động sẽ phải thực hiện các tìm kiếm gần để tìm POI gần đó (điểm os quan tâm). Tôi biết đó là một kịch bản rất phổ biến và trông rất đơn giản, nhưng có nhiều cách khác nhau tôi có thể thực hiện nó, vì vậy tôi rất thích xem các chuyên gia giàu kinh nghiệm hơn đang thực hiện các tìm kiếm không gian đơn giản này như thế nào.
Vì POI chỉ là một ĐIỂM, chúng tôi không cần bất kỳ phép tính phức tạp nào liên quan đến giao lộ hoặc tương tự. Đó là lý do ban đầu tôi nghĩ rằng việc sử dụng các cột và chỉ số không gian GEOGRAPHY có thể là quá mức hoặc thậm chí chậm hơn các chiến lược khác. Vì vậy, tôi đã thu hẹp nó xuống còn 3 cách tiếp cận:
1) Cột GEOGRAPHY + Chỉ số không gian
Đây có lẽ là giải pháp thực tế cho vấn đề này. Vì chúng tôi có các chỉ mục không gian và cột địa lý, chúng tôi chỉ có thể sử dụng nó và tìm kiếm theo khoảng cách. Một cái gì đó như thế này.
SELECT * FROM POIs WHERE Loc.STDistance(@radius) <= @distance;
Vì chúng tôi có chỉ số không gian trên Lộc, nên sẽ rất nhanh.
2) Sử dụng "hộp giới hạn" trên các cột Vĩ độ và Kinh độ
Đây là cách tiếp cận tầm thường mà không liên quan đến các chỉ số không gian. Chúng tôi tìm thấy một hộp giới hạn cho điểm và bán kính của chúng tôi sau đó chỉ cần tìm kiếm trên các cột Vĩ độ và Kinh độ. Nếu cả hai được lập chỉ mục tìm kiếm này sẽ rất nhanh. Chúng ta sẽ phải áp dụng hàm khoảng cách để lọc ra một số giá trị bên ngoài "vòng tròn" nhưng không có hộp giới hạn. Nhưng điều đó sẽ khá nhanh. Ý tưởng này được giải thích tốt hơn ở đây: http://www.movable-type.co.uk/scripts/latlong-db.html
Một cái gì đó như thế này:
DECLARE @lat float
DECLARE @lon float
SET @lat = -23.001029
SET @lon = -43.328422
DECLARE @maxLat float, @minLat float, @maxlon float, @minLon float
DECLARE @R float
DECLARE @distance FLOAT = 100 -- A distance in meters
SET @R = 6378137 -- Earth
SET @maxLat = @lat + DEGREES(@distance/@R)
SET @minLat = @lat - DEGREES(@distance/@R)
SET @maxLon = @lon + DEGREES((@distance/@R/COS(RADIANS(@lat))))
SET @minLon = @lon - DEGREES((@distance/@R/COS(RADIANS(@lat))))
SELECT * from POIs
WHERE
Lat Between @minLat And @maxLat
And Lng Between @minLon And @maxLon
3) Sử dụng GEOHASH tích hợp được lưu trữ trên cột được lập chỉ mục
Cách tiếp cận này rất thú vị và đó là thứ mà mọi người đang sử dụng cùng với các bộ được đặt hàng của REDIS để thực hiện tìm kiếm gần. Nguyên tắc có thể được chuyển sang SQL Server bằng cách sử dụng một cột được lập chỉ mục lưu trữ GEOHASH tích hợp.
Tôi đã có ý tưởng này từ Ardb: https://github.com/yinqiwen/ardb/wiki/Spatial- Index
Nó cũng được giải thích theo cách thân thiện hơn ở đây: Sử dụng geohash cho các tìm kiếm gần?
Nói cách khác, người ta sẽ tính toán GEOHASH với độ sâu bit tương ứng với bán kính của tìm kiếm mà người ta mong muốn, sau đó tính toán 8 geohash geohash và cuối cùng gửi tìm kiếm bằng cách sử dụng các geohash này dưới dạng các hộp giới hạn trên cột được lập chỉ mục. Đây sẽ là 9 toán tử GIỮA trên mệnh đề WHERE của SQL ... Các kết quả sẽ phải được lọc do một số POI giả được trả về.
Nhưng có vẻ như điều này sẽ chậm hơn phương thức 2 vì mệnh đề where sẽ phức tạp hơn mặc dù nó sẽ chỉ truy vấn trên một cột thay vì hai.
Có ai có bất kỳ kinh nghiệm để chia sẻ về điều này? Có một cách tiếp cận tốt hơn / chính xác cho điều này?