sql >> Database teknologi >  >> RDS >> PostgreSQL

Rumlig forespørgsel på et stort bord med flere selvstændige joinforbindelser, der udfører langsomt

Denne forespørgsel bør række langt (være meget hurtigere):

WITH school AS ( SELECT s.osm_id AS school_id, text 'school' AS type, s.osm_id, s.name, s.way_geo FROM planet_osm_point s , LATERAL ( SELECT 1 FROM planet_osm_point WHERE ST_DWithin(way_geo, s.way_geo, 500, false) AND amenity ='bar' LIMIT 1 -- bar eksisterer -- mest selektive først hvis muligt ) b , LATERAL ( SELECT 1 FROM planet_osm_point WHERE ST_DWithin(way_geo, s.way_geo, 500, false) OG amenity ='restaurant' LIMIT 1 -- restaurant findes ) r HVOR s.amenity ='skole' )VÆLG * FRA (TABEL skole -- skoler UNION ALLE -- barer SELECT s.school_id, 'bar', x.* FRA skole s , LATERAL ( SELECT osm_id, name, way_geo FROM planet_osm_point WHERE ST_DWithin(way_geo, s.way_geo, 500, false) AND amenity ='bar' ) x UNION ALL -- restauranter VÆLG s.school_id, 'rest.', x. * FRA skole s , LATERAL (VÆLG osm_id, navn , way_geo FROM planet_osm_point WHERE ST_DWithin(way_geo, s.way_geo, 500, false) AND amenity ='restaurant' ) x ) underORDER BY school_id, (type <> 'school'), type, osm_id;

Dette er ikke det samme som din oprindelige forespørgsel, men snarere hvad du faktisk ønsker, i henhold til diskussion i kommentarer :

Så denne forespørgsel returnerer en liste over disse skoler efterfulgt af barer og restauranter i nærheden. Hvert sæt rækker holdes sammen af ​​osm_id af skolen i kolonnen school_id .

Bruger nu LATERAL joins, for at gøre brug af det rumlige GiST-indeks.

TABLE-skole er kun en forkortelse for SELECT * FROM school :

Udtrykket (type <> 'skole') bestiller skolen i hvert sæt først, fordi:

Underforespørgslen sub i den sidste SELECT er kun nødvendig for at bestille efter dette udtryk. En UNION forespørgsel begrænser en vedhæftet ORDER BY liste til kun kolonner, ingen udtryk.

Jeg fokuserer på den forespørgsel, du præsenterede med henblik på dette svar - ignorering det udvidede krav om at filtrere på en af ​​de andre 70 tekstkolonner. Det er virkelig en designfejl. Søgekriterierne bør være koncentreret i kolonner. Eller du bliver nødt til at indeksere alle 70 kolonner, og indekser med flere kolonner, som jeg vil foreslå, er næppe en mulighed. Stadig muligt selvom ...

Indeks

Ud over det eksisterende:

"idx_planet_osm_point_waygeo" hovedindhold (way_geo) 

Hvis du altid filtrerer på den samme kolonne, kan du oprette en indeks med flere kolonner dækker de få kolonner, du er interesseret i, så index- kun scanninger blive muligt:

OPRET INDEX planet_osm_point_bar_idx PÅ planet_osm_point (bekvemmelighed, navn, osm_id) 

Postgres 9.5

Den kommende Postgres 9.5 introducerer store forbedringer der tilfældigvis adresserer din sag præcist:

Det er af særlig interesse for dig. Nu kan du få en enkelt multikolonne (dækkende) GiST-indeks:

OPRET INDEX reservations_range_idx ON reservationsUSING gist(amenity, way_geo, name, osm_id) 

Og:

Og:

Hvorfor? Fordi ROLLUP ville forenkle den forespørgsel, jeg foreslog. Relateret svar:

Den første alfaversion er blevet frigivet den 2. juli 2015. Den forventede tidslinje for udgivelsen:

Grundlæggende

Sørg selvfølgelig for ikke at overse det grundlæggende:



  1. databaseskema for produktattributter

  2. Oracle Cloud Breakdown – Databasehostingomkostninger på OCI

  3. Hvordan tæller man alle de forbundne noder (rækker) i en graf på Postgres?

  4. I tsql er en Insert med en Select-sætning sikker med hensyn til samtidighed?