2012-08-07 9 views
6

Chciałbym wiedzieć, co ludzie sugerują, jako wydajne sposoby wykonywania kwerendy przestrzennej w usłudze Amazon Web Services SimpleDB?Zapytania przestrzenne na temat AWS SimpleDB

Przez kwerendę przestrzenną rozumiem obiekty znajdujące się w określonym promieniu szerokości i długości geograficznej.

Odpowiedz

14

SimpleDB obecnie nie oferuje żadnych wbudowanych operacji wyszukiwania przestrzennego, ale nie oznacza to, że nie można tego zrobić. Istnieje kilka metod implementacji wyszukiwania geoprzestrzennego w nie-geoprzestrzennie świadomych bazach danych, takich jak SimpleDB i wszystkie koncentrują się wokół idei korzystania z bazy danych w celu pobrania wstępnej pierwszej selekcji w oparciu o ramkę ograniczającą geoprzestrzenie, a następnie filtrowania zwróconych danych w aplikacji za pomocą dokładniejsze algorytmy, takie jak Haversine formula.

Ty mógł sklep szerokości i długości geograficznej jako (zero-wyściełane i znormalizowane) atrybutów numerycznych, a następnie wykonać podwójne zapytanie range (lat >= minLat and lat <= maxLat and lon >= minLat and lon <= maxLat), ale ponieważ żaden z theese orzeczników są selektywne (każde orzeczenie odpowiada wiele elementów) nie jest idealny (patrz Tuning Queries).

Lepszym sposobem byłoby użycie GeoHashes.

Geohashes oferują właściwości jak arbitralnej precyzji, podobne przedrostki dla pobliskich stanowiskach oraz możliwość stopniowego usuwania znaków od końca kodu w celu zmniejszenia jego wielkości (i stopniowo utratę precyzji).

Jako praktyczny przykład, Geohash 6gkzwgjzn820 dekoduje do współrzędne -25,382708 i -49,265506, natomiast Geohash 6gkzwgjz będzie dekodowania do -25.383 -49.266 i, a jeśli weźmiemy podobną pozycję w tym samym regionie, takich jak -2,427 i -49,315, widzimy, że jest to zakodowane jako 6gkzmg1w (zauważ podobny przedrostek).

Od http://geohash.org/site/tips.html

ze swoimi pozycjami Rzecz jak GeoHashes można użyć operatora like aby wyszukać obwiedni (where GeoHash like '6gkzmg1w%'), ale ponieważ operator like jest drogie (Comparison Operators) lepszym sposobem byłoby denormalize dane poprzez przechowywanie każdego prefiksu GeoHash (ile zależy od wymaganej precyzji wyszukiwania) jako oddzielnego atrybutu (GeoHash6 GeoHash8 itp.), a następnie użyj prostego predykatu równości (where Geohash8 = '6gkzmg1w').

Teraz na minus GeoHashów. Ponieważ nie możesz założyć, że GeoHash jest wyśrodkowany w twoim polu wyszukiwania, musisz również przeszukać wszystkie sąsiednie prefiksy. Proces jest doskonale opisany geohash-js

Geohash posiada tę właściwość, że ponieważ liczba cyfr zmniejsza (z prawej strony), dokładność spada. Ta właściwość może być używana do wyszukiwania ramek ograniczających, ponieważ punkty bliskie sobie nawzajem będą udostępniać podobne przedrostki Geohash.

Jednakże, ponieważ dany punkt może pojawić się na krawędzi danego Geohash Obwiednia, konieczne jest, aby wygenerować listę Geohash wartości w celu przeprowadzenia prawdziwej szukanie bliskości wokół punktu. Ponieważ algorytm Geohash stosuje się system numeracji bazowy 32 jest możliwe uzyskanie wartości Geohash wokół innej podanej wartość Geohash za pomocą prostego tabeli.

Tak więc, na przykład, 1600 Pennsylvania Avenue, Waszyngton postanawia: 38,897, -77,036

Stosując algorytm geohash, to szerokość i długość geograficzna jest przekształcany do: dqcjqcp84c6e

Prosty obwiedni wokół tego punktu może być opisany przez obcinania ten geohash do: dqcjqc

jednak „dqcjqcp84c6e” nie jest wyśrodkowany wewnątrz „dqcjqc” i szukają w „dqcjqc” może przegapić jakąś pożądaną Tarcza ts.

Zamiast tego możemy użyć matematycznych właściwości Geohash do szybko obliczyć sąsiadów "dqcjqc"; okazuje się, że są one: 'dqcjqf', 'dqcjqb', 'dqcjr1', 'dqcjq9', 'dqcjqd', 'dqcjr4', 'dqcjr0', 'dqcjq8'

To daje nam obwiedni wokół ' dqcjqcp84c6e "około 2 km x 1,5 km i pozwala na wyszukiwanie w bazie danych tylko 9 klawiszy: WYBIERZ * Z tabeli GDZIE LEWE (geohash, 6) IN (" dqcjqc ", " dqcjqf "," dqcjqb "," dqcjr1 ", "dqcjq9", "dqcjqd", "dqcjr4", "dqcjr0", "dqcjq8");

Przetłumaczony na zapytania SimpleDB Byłoby where GeoHash6 in('dqcjqc', 'dqcjqf', 'dqcjqb', 'dqcjr1', 'dqcjq9', 'dqcjqd', 'dqcjr4', 'dqcjr0', 'dqcjq8') a potem zrobi swoje Haversine filtrowanie na wyniki w celu uzyskania tylko te elementy, które znajduje się w zasięgu promienia wyszukiwania.

+0

Doskonała odpowiedź, dzięki za dyskusję na Geohashes – user293895

0

Zostawię to tutaj, ponieważ może ci pomóc!

14 lat temu staraliśmy się zrobić geo lookup table lokalizacji w promieniu. Oczywiście nie było żadnych indeksów geoprzestrzennych ani nic w tym stylu. Nie było dosłownie tylko standardowe SQL i Oracle ... w każdym razie, konwertowaliśmy wszystkie lat/lng na kilometry ze stałego pola płaszczyzny. Zasadniczo jakie indeksy geoprzestrzenne robią w dzisiejszych czasach.

Aby wyjaśnić, co dokładnie robi, zmienia świat w płaską powierzchnię, a przy odrobinie podejrzeń SQL można nawet wybrać za pomocą promienia, a nawet uzyskać odległość od dwóch punktów, które wybierasz. Ponieważ jest to również surowe pełne liczby całkowite, zapytania szybko się palą.

Oto prosty przykład w PHP i bardzo skomplikowane patrząc jednak dość proste, gdy zrozumieć zapytanie SQL:

https://gist.github.com/tobsn/899413