2012-05-05 58 views
11

Używam następujący najbliższego sąsiada kwerend w PostGIS:K-Najbliższy sąsiad Zapytanie w PostGIS

SELECT g1.gid g2.gid FROM points as g1, polygons g2 
WHERE g1.gid <> g2.gid 
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom) 
LIMIT k; 

teraz, że stworzyliśmy indeksy na the_geom jak gid kolumnowej na obu tablicach, to zapytanie jest zajmuje dużo więcej czasu niż inne zapytania przestrzenne związane z połączeniami przestrzennymi b/w dwie tabele.

Czy istnieje lepszy sposób na znalezienie najbliższych sąsiadów K? Używam PostGIS.

I kolejna kwerenda, która bierze niezwykle długo, mimo tworzenia indeksów na kolumny geometrii:

select g1.gid , g2.gid from polygons as g1 , polygons as g2 
where st_area(g1.the_geom) > st_area(g2.the_geom) ; 

wierzę, te pytania arent korzystał przez indeksy GIST, ale dlaczego?

niniejsza zapytania:

select a.polyid , sum(length(b.the_geom)) from polygon as a , roads as b 
where st_intersects(a.the_geom , b.the_geom); 

powraca spowodować po pewnym czasie mimo udziałem „dróg” stół, który jest znacznie większy niż wielokątów lub punkty tabeli i obejmować również bardziej złożone operatory przestrzenne.

+0

Zakładam, że pytanie, jak przyspieszyć zapytanie? Czy możesz pokazać nam wyniki WYBUCHUJ ANALIZA WYBIERZ ....? W ten sposób moglibyśmy wiedzieć, co się tam dzieje. – Thilo

+0

Nie, moje pytanie brzmi: dlaczego to pytanie zajmuje więcej niż 5 razy więcej czasu niż trzecie pytanie powyżej !! –

+0

ok, po mniej więcej oczekiwaniu, dla IInd Query otrzymuję następujący komunikat o błędzie: "brak pamięci dla wyniku zapytania" i wykonanie zapytania zostało zakończone. Czy ktoś może rzucić na to światło? –

Odpowiedz

6

Zaledwie kilka myśli na temat swojego problemu:

st_distance jak st_area nie są w stanie korzystać z indeksów. Jest tak dlatego, że obie funkcje nie mogą być zredukowane do pytań typu "Czy jest w b?" lub "Czy nakładają się a i b?". Jeszcze bardziej konkretny: wskaźniki GIST mogą działać tylko na obwiedniach dwóch obiektów.

Aby uzyskać więcej informacji na ten temat, wystarczy spojrzeć na numer postgis manual, który podaje przykład ze st_distance i jak można ulepszyć zapytanie, aby działał lepiej.

Nie rozwiąże to jednak problemu k-najbliższego-sąsiada. W tym momencie nie mam dobrego pomysłu, jak poprawić wydajność zapytania. Jedyną szansą, jaką widzę, byłoby założenie, że najbliżsi sąsiedzi są zawsze w odległości poniżej x metrów. Następnie można zastosować podobne podejście, jak w przypadku instrukcji postgis.

Twoje drugie zapytanie może zostać nieco przyspieszone. Obecnie oblicza się obszar dla każdego obiektu w tabeli 1 tak często, jak tabela zawiera wiersze - strategia najpierw łączy dane, a następnie wybiera na podstawie tej funkcji. Można zmniejszyć liczbę obliczeń strefy istotnie być precomputing zakresie:

WITH polygonareas AS (
    SELECT gid, the_geom, st_area(the_geom) AS area 
    FROM polygons 
) 
SELECT g1.gid, g2.gid 
FROM polygonareas as g1 , polygonareas as g2 
WHERE g1.area > g2.area; 

Trzecie zapytanie może być znacznie zoptymalizowane za pomocą obwiedni: Kiedy obwiedni dwóch obiektów nie pokrywają się, nie ma sposobu, obiekty zrobić . Pozwala to na użycie danego indeksu, a tym samym ogromny wzrost wydajności.

14

Od late September 2011, PostGIS wsparła indeksowane najbliższego sąsiada kwerend za pomocą specjalnego operatora (-ów) użyteczna w klauzuli ORDER BY:

SELECT name, gid 
FROM geonames 
ORDER BY geom <-> st_setsrid(st_makepoint(-90,40),4326) 
LIMIT 10; 

... zwróci 10 obiektów, których geom jest najbliższy -90,40 w skalowalny sposób.Kilka dalszych szczegółów (opcji i zastrzeżeń) znajduje się w tym ogłoszeniu: post i use of the <-> i the <#> operators jest również teraz udokumentowane w oficjalnym referencji PostGIS 2.0. (Główną różnicą między nimi jest, że <-> porównuje centroidy kształt i <#> porównuje swoje granice. - nie ma znaczenia dla punktów, inne kształty wybrać to, co jest właściwe dla zapytań)

+1

Głównym zastrzeżeniem tych dwóch operatorów, jak to wskazuje na powiązanych stronach referencyjnych postgis, jest to, że indeks przestrzenny włączy się tylko wtedy, gdy jedna z geometrii jest stała, jak w twoim st_makepoint w przykładzie. Oznacza to, że nie można używać tych operatorów z wydajnym użyciem indeksu do odpowiedzi na pytanie OP, które wymaga znalezienia wszystkich geometrii A w pobliżu jakiegoś innego zestawu geometrii B. –

+0

Ach, dobra uwaga. Dziękuję za podniesienie. Czy zatem odpowiedź Stefana brzmi "poprawna", potrzebująca nieco więcej szczegółów i zaktualizowanych linków? – natevw

0

Zakładając, że punkt P i G wielokątów, twój oryginalne zapytanie:

SELECT g1.gid, g2.gid FROM points as g1, polygons g2 
WHERE g1.gid <> g2.gid 
ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom) 
LIMIT k; 

Powraca k najbliższych sąsiadów w zestawie pxg. Zapytanie może wykorzystywać indeksy, ale wciąż musi zamówić cały zbiór p x g, aby znaleźć k wierszy o najmniejszej odległości. To, czego zamiast tego chcesz, to:

SELECT g1.gid, 
     (SELECT g2.gid FROM polygons g2 
     --prevents you from finding every nearest neighbour twice 
     WHERE g1.gid < g2.gid 
     --ORDER BY gid is erroneous if you want to limit by the distance 
     ORDER BY ST_Distance(g1.the_geom,g2.the_geom) 
     LIMIT k) 
FROM points as g1;