Tento dotaz by měl jít dlouhou cestou (být hodně rychlejší):
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 exists -- most selective first if possible
) b
, LATERAL (
SELECT 1 FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'restaurant'
LIMIT 1 -- restaurant exists
) r
WHERE s.amenity = 'school'
)
SELECT * FROM (
TABLE school -- schools
UNION ALL -- bars
SELECT s.school_id, 'bar', x.*
FROM school 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 -- restaurants
SELECT s.school_id, 'rest.', x.*
FROM school s
, LATERAL (
SELECT osm_id, name, way_geo
FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'restaurant'
) x
) sub
ORDER BY school_id, (type <> 'school'), type, osm_id;
Toto není stejné jako váš původní dotaz, ale spíše to, co skutečně chcete, dle diskuze v komentářích :
Tento dotaz tedy vrátí seznam těchto škol následovaný bary a restauracemi v okolí. Každá sada řádků je držena pohromadě pomocí osm_id
školy ve sloupci id_školy
.
Nyní pomocí LATERAL
spojení, aby bylo možné využít prostorový index GiST.
TABLE škola
je jen zkratka pro SELECT * FROM school
:
Výraz (typ <> 'škola')
objednává školu v každé sadě jako první, protože:
Poddotaz sub
ve finálním SELECT
je potřeba pouze objednat tímto výrazem. UNION
dotaz omezuje připojený ORDER BY
seznam pouze na sloupce, žádné výrazy.
Zaměřuji se na dotaz, který jste uvedli pro účely této odpovědi - ignorování rozšířený požadavek na filtrování podle kteréhokoli z dalších 70 textových sloupců. To je opravdu konstrukční vada. Kritéria vyhledávání by měla být soustředěna do několika sloupců. Nebo budete muset indexovat všech 70 sloupců a vícesloupcové indexy, jako budu navrhovat, jsou jen stěží možností. Stále možné ačkoli ...
Index
Kromě stávajícího:
"idx_planet_osm_point_waygeo" gist (way_geo)
Pokud vždy filtrujete podle stejného sloupce, můžete vytvořit vícesloupcový index pokrývající několik sloupců, které vás zajímají, takže index- pouze skenuje staly možnými:
CREATE INDEX planet_osm_point_bar_idx ON planet_osm_point (amenity, name, osm_id)
Postgres 9.5
Nadcházející Postgres 9.5 představuje hlavní vylepšení které přesně řeší váš případ:
To tě obzvlášť zajímá. Nyní můžete mít single vícesloupcový (krycí) index GiST:
CREATE INDEX reservations_range_idx ON reservations
USING gist(amenity, way_geo, name, osm_id)
A:
A:
Proč? Protože ROLLUP
by zjednodušil dotaz, který jsem navrhl. Související odpověď:
První alfa verze byla vydána 2. července 2015. Očekávaný časový rozvrh vydání:
Základy
Samozřejmě nezapomeňte na základní věci: