Mam dane OpenStreetMap dla Holandii załadowane do bazy danych PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) przy użyciu schematu osmozy . Oznacza to, że wszystkie tagi są przechowywane w polu hstore . Oprócz indeksu GIST, który osmoza tworzy na polu geometrii, utworzyłem dodatkowy indeks GIST na polu tagów.
Próbując wykonać zapytanie przy użyciu zarówno ograniczenia przestrzennego, jak i ograniczenia w polu znaczników, stwierdzam, że jest on wolniejszy niż chciałbym. Zapytanie takie jak to:
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n
INNER JOIN users AS u ON n.user_id = u.id
WHERE tags->'man_made'='surveillance'
AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));
Zwrócenie 78 rekordów zajmuje 22 sekundy.
W tej tabeli znajduje się około 53 milionów rekordów.
Czy istnieje sposób, aby znacznie to przyspieszyć? Słyszałem, że hstore jest znacznie lepiej zaimplementowany w PostgreSQL 9, czy aktualizacja pomogłaby?
Odpowiedzi:
Jedną z metod byłoby zapytanie o interesujące cię tagi i umieszczenie tych rekordów w nowej tabeli. W takim razie wystarczy zapytać nową tabelę zamiast wszystkich 53 milionów rekordów. Jeśli próbujesz aktualizować bazę danych, możesz uruchomić to zapytanie za każdym razem, gdy otrzymujesz nowe dane z OSM.
źródło
Możesz spróbować utworzyć indeks dla kolumny hstore,
a następnie użyj
?
operatora, aby ograniczyć zapytanie tylko do tych wierszy:źródło
?
operatora zajęło 48 sekund w porównaniu do 88 sekund na moje zapytanie (nie wiem, jak wczoraj otrzymałem 72 sekundy, być może maszyna tym razem robiła coś skomplikowanego podczas wykonywania zapytań). Wciąż nie szukam wydajności, ale lepiej zrozumiałem, w jaki sposób indeksy GIST działają na kolumnach hstore. Nadal będę musiał wybrać inne rozwiązanie polegające na stworzeniu zmaterializowanego widoku, aby uzyskać żądaną wydajność.Funkcje st_within i _st_within nie są znane ze swojej szybkości. Operator && może pomóc, ponieważ sprawdzi bbox zamiast geometrii
Możesz spróbować:
Więcej wskazówek dotyczących wydajności można znaleźć na stronie: http://postgis.refractions.net/docs/ch06.html
źródło
Problem z zapytaniem stanowi
tags->'man_made'='surveillance'
klauzula. Zmusza to Postgres do rozszerzenia tagów hstore i nie pozwala na korzystanie z indeksu. Jeśli przepiszesz to za pomocą@>
(zawiera), pozwoli to na użycie indeksu.Ponieważ
&&
pytasz o prostokąt, możesz użyć zamiast ST_Within. Będzie to miało niewielki zysk, ponieważ ST_Within nie jest tak skomplikowany do oceny, a ST_Within niejawnie&&
sprawdza.Dodatkowym wzrostem prędkości byłoby użycie indeksu GIN na tagach zamiast indeksu GIST. Indeksy GIN trwają dłużej, ale są szybsze.
Całe zapytanie byłoby
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);
Jeśli wiesz, że często wysyłasz zapytanie do określonego znacznika, możesz utworzyć na nim częściowy indeks
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Umożliwi to warunek WHERE
tags->'man_made'='surveillance'
użycie indeksu. Niestety, ten indeks nie może pomóc@>
zapytaniom, a indeksy GIN lub GIST nie mogą pomóctags->'foo'
zapytaniom, więc musisz dopasować zapytania do posiadanych indeksów.źródło
tags @>hstore()
znacznie poprawiłem moje zapytanie, dzięki.spróbuj tego zamiast tego:
WYBIERZ n.geom, n.tagi, n.tampa, u.nazwa z węzłów AS n INNER JOIN users AS u ON n.user_id = u.id GDZIE tagi @> 'man_made => monitoring' :: hstore AND ST_Within (geom , ST_GeomFromText („POLYGON ((4,0 52,0,5,0 52,0,5,0 53,0,0,0 53,0,0,0 52,0))”, 4326));
źródło