PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Пространствена заявка за голяма маса с множество самосъединявания, изпълняващи се бавно

Тази заявка трябва да измине дълъг път (да бъде много по-бързо):

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;

Това ене същото като оригиналната ви заявка, но по-скоро това, което всъщност искате, според дискусията в коментарите :

Така че тази заявка връща списък с тези училища, последван от барове и ресторанти наблизо. Всеки набор от редове се държи заедно от osm_id на училището в колоната school_id .

Сега се използва LATERAL се присъединява, за да използва пространствения GiST индекс.

Училище TABLE е просто съкращение за SELECT * FROM school :

Изразът (тип <> 'училище') нарежда първо училището във всеки комплект, защото:

Подзаявката sub в крайния SELECT е необходимо само за подреждане по този израз. СЪЮЗ заявката ограничава прикачен ORDER BY списък само към колони, без изрази.

Съсредоточавам се върху заявката, която представихте за целите на този отговор - игнориране разширеното изискване за филтриране на която и да е от останалите 70 текстови колони. Това наистина е дефект в дизайна. Критериите за търсене трябва да бъдат концентрирани в няколко колони. Или ще трябва да индексирате всичките 70 колони, а многоколонните индекси, каквито ще предложа, едва ли са опция. Все още възможно въпреки че...

Индекс

В допълнение към съществуващите:

"idx_planet_osm_point_waygeo" gist (way_geo)

Ако винаги филтрирате една и съща колона, можете да създадете многоколонен индекс обхващайки няколкото колони, които ви интересуват, така че index- само сканира стане възможно:

CREATE INDEX planet_osm_point_bar_idx ON planet_osm_point (amenity, name, osm_id)

Postgres 9.5

Предстоящият Postgres 9.5 въвежда основни подобрения които отговарят точно на вашия случай:

Това е от особен интерес за вас. Сега можете да имате сингъл многоколонен (покриващ) GiST индекс:

CREATE INDEX reservations_range_idx ON reservations
USING gist(amenity, way_geo, name, osm_id)

И:

И:

Защо? Тъй като ROLLUP ще опрости заявката, която предложих. Свързан отговор:

Първата алфа версия беше пусната на 2 юли 2015 г. Очакваният график за изданието:

Основни положения

Разбира се, не пропускайте основните неща:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Грешка:Импортиране на база данни на Postgres в докер контейнер

  2. Rails Свързване към база данни, зададена от database.yml

  3. Връщане на дублирани записи (activerecord, postgres)

  4. Postgresql varchar брои ли се с помощта на дължина на знака в unicode или дължина на символа в ASCII?

  5. Името на таблица или колона не може да започва с число?