2009-05-14 9 views
7

Chcę utworzyć dużą bazę danych współrzędnych GPS, które można sprawdzić, mówiąc "Zwróć wszystkie współrzędne, które są w obrębie" n "liczników [tej współrzędnej]".Przechowywanie i kwerendowanie współrzędnych GPS Efektywnie

Potrzebuję, aby był tak wydajny, jak to możliwe, więc zapętlenie wszystkich współrzędnych w bazie danych i obliczenie, czy współrzędne są w granicach "n", nie byłoby pożądanym rozwiązaniem.

Czy istnieje łatwiejsze rozwiązanie?

Dzięki

Odpowiedz

2

Jest wsparcie w SQL Server 2008 do przechowywania spatial data. Nigdy z nim nie współpracowałem, ale wiem, że możesz tworzyć zapytania tego typu, jakiego chcesz.

0

Jeśli masz wybór DB, polecam takie same jak rwwilden i używać SQL 2008 z jego możliwości przestrzennych danych. Jeśli nie możesz użyć tego rozwiązania lub takiego, które zawiera kwerendy przestrzenne, możesz rzucić okiem na własny dokument Microsoftu na Hierarchical Triangular Mesh i zaimplementować te rzeczy. Pakiet SDK dla MSSQL '05 przyszedł z kompletnym rozwiązaniem dla HTM zaraz po wyjęciu z pudełka, więc możesz po prostu wziąć to i przekonwertować na dowolną platformę, której szukasz.

EDIT:

Oto więcej szczegółów document wyjaśniając HTM i wdrażania. Możesz oczywiście przekonwertować do wybranego DB. Możesz znaleźć kod źródłowy do pełnej implementacji HTM w SDK na rok 2005.

0

Bazy danych GIS (MS PostgreSQL itp.) Faktycznie implementują pewną strukturę danych dla dwu- lub trójwymiarowych wyszukiwania regionu (spatial indices). Najprostszą surowicą jest indeks siatki, następnie różne drzewa wyszukiwania (drzewo-kd, drzewo-kwadrat) z najczęściej używanym drzewem R (uogólnione drzewo B dla większej liczby wymiarów). Te metody wydają się odpowiednie.

Podstawowy indeks sieci (dzielenie przestrzeni na komórki siatki i wyszukiwanie tylko w pobliskich komórkach) może być łatwo zaimplementowany i może skrócić czas wyszukiwania do logarytmu. Drzewa wyszukiwania są nieco trudniejsze do wdrożenia, ale istnieje wiele wdrożeń open-source dla wielu języków programowania. Jednak w większości przypadków indeksacja sieci jest wystarczająco wydajna.

6

Zazwyczaj wykonuję tego rodzaju zapytanie, używając lat/lon. Używając geometrii sferycznej, możesz umieścić obwiednię wokół określonego punktu. Załóżmy na przykład, że masz punkt (X, Y), który ma mieć wszystkie współrzędne w promieniu 1 mili (przeliczenie na metry pozostawię jako ćwiczenie dla czytelnika). Możesz określić ramkę ograniczającą (X-1, Y-1), (X + 1, Y + 1). Następnie wyszukujesz bazę punktów za pomocą operatora BETWEEN (SELECT foo FROM bar WHERE LAT MIĘDZY X-1 A X + 1 I LON MIĘDZY Y-1 I Y + 1). Następnie wykonujesz szczegółowe obliczenia odległości, aby "zaokrąglić rogi" obwiedni.

Ograniczeniem jest to, że linie długości są bliżej siebie u góry kuli, więc uzyskasz skośne wyniki, im dalej jesteś od równika. Ale nadal służy do szybkiego odfiltrowania twoich zestawów wyników.

Google "Wielka odległość koła" do obliczeń.

EDIT: Istnieje 0.167469 stopnie długości jednej mili (w rzeczywistości waha się od 0.167469 do 0.014564), a 0.014483 stopnie szerokości jednej mili. Tak więc twoja ramka ograniczająca to (lat - (miles * 0.014483), lon - (miles * 0.167469)), (lat + (miles * 0.014483), lon + (miles * 0.167469))

0

Nawiązując do Ericha - jeśli masz wybór, użyj PostGIS (postgresql), to jest bezpłatne i open source, czy zapytania, które opisujesz bardzo szybko, działają na prawie wszystkich platformach i czy ja wspomnieć, że jest za darmo?

0

Jeśli chcesz uniknąć rozszerzenia GIS, ja dostosować funkcje z this post do postgres SQL:

create or replace function change_in_lat(miles numeric) 
returns double precision as $$ 
with v as (select 
    3960.0 as earth_radius, 
    180/pi() as radians_to_degrees 
) select (miles/earth_radius) * radians_to_degrees from v; 
$$ language sql 
returns null on null input; 

create or replace function change_in_long(lat numeric, miles numeric) 
returns double precision as $$ 
with v as (select 
    3960.0 as earth_radius, 
    pi()/180 as degrees_to_radians, 
    180/pi() as radians_to_degrees 
) select (
    miles/(earth_radius * cos(lat * degrees_to_radians)) 
    ) * radians_to_degrees from v; 
$$ language sql 
returns null on null input; 

używając tych można zrobić kilka okolicznych kwadratowych wyszukiwania:

--find all "a"s within 25 miles of any "b" 
select * from a join b on (
a.gpslat between 
    b.gpslat - change_in_lat(25) and b.gpslat + change_in_lat(25) 
and a.gpslong between 
    b.gpslong - change_in_long(b.gpslat::numeric, 25) 
    and b.gpslong + change_in_long(b.gpslat::numeric, 25) 
); 

jeśli używał go dość często. Jestem pewien, że przekształcenie instrukcji między dwiema funkcjami w jedną funkcję byłoby łatwe. Jednak nigdy nie robiłem żadnych faktycznych zapytań "w promieniu".

Jeśli chodzi o coś bardziej skomplikowanego, prawdopodobnie będziesz potrzebować rozszerzenia GIS, tak jak inne odpowiedzi. PostGIS jest dobry, ale odkryłem, że wiele funkcji specyficznych dla gis może być trudnych do uzyskania, i jeśli nie wykorzystasz indeksów ograniczających pola, zapytania przestrzenne mogą zająć dzień, jeśli twój zestaw danych będzie wystarczająco duży. Ale kompromis w złożoności jest zdecydowanie warta wszystkich fantazyjnych rzeczy, takich jak wyprowadzanie danych w formacie geojsona, itp.

Powiązane problemy