Простая проблема соединения запросов со столбцом PostGIS на Postgresql - PullRequest
0 голосов
/ 30 мая 2019

Мой запрос очень медленный, и мне нужно улучшить скорость (приведено ниже описание базы данных)

Мне нужно создать один запрос, который может:

  1. Сначала выберите все place_ids из place_table в радиусе
  2. Затем, используйте place_ids , чтобы найти все item_ids в items_table
  3. Затем отфильтруйте выбранные item_ids по:
    • , определяя, содержит ли item_id определенный ключв items_indexed_table (Например: SELECT * FROM items_indexed_table WHERE key = 'foo_bar')
    • определение, имеет ли этот элемент определенный цвет в таблице item_colors_table

Я создал несколько запросов, но они выполняются медленно (> 1 мин).Я считаю, что все таблицы правильно проиндексированы и используются, когда я запускаю EXPLAIN ANALYZE.Запросы JOIN и WITH AS () не помогают при попытке применить все описанные выше шаги.

Однако, когда я выполняю шаги 1 и 2 в одном запросе, он возвращает результаты менее чем за 500 мс, а когда я запускаю шаг3 только для определенного ключа и цвета, он также возвращает результаты менее чем за 500 мс.Проблема в том, что когда я пытаюсь присоединиться к ним, получение возврата занимает очень много времени.Я запустил EXPLAIN ANALYZE и обнаружил, что шаги 1 и 2 были выполнены последними.

Ниже приведены два запроса, упомянутых выше:

with nearest_items AS (
  with nearest_places AS (
    SELECT place_id
    FROM places_table
    WHERE (ST_DWithin(places_table.geometry, ST_MakePoint(some_lon, some_lat)::geography, 1500))
  )
  SELECT items_table.item_id
  FROM items_table
  WHERE items_table.place_id IN (SELECT place_id FROM nearest_places)
) SELECT * FROM nearest_items;

Время планирования: 0,457 мс

Время выполнения: 36,420 мс

Но когда я объединяю его, чтобы использовать его с item_indexed_table , скорость очень низкая.

with nearest_items AS (
  with nearest_places AS (
    SELECT place_id
    FROM places_table
    WHERE (ST_DWithin(places_table.geometry, ST_MakePoint(some_lon, some_lat)::geography, 1500))
  )
  SELECT items_table.item_id
  FROM items_table
  WHERE items_table.place_id IN (SELECT place_id FROM nearest_places)
) 
SELECT
       items_table.item_id
FROM
     items_table
WHERE
      items_tables.item_id in (
         SELECT *
         FROM nearest_items
         )
  and items_table.item_id in (
         SELECT item_id
         FROM item_indexed_table
         WHERE key = 'medicine'
         )
;

Вот ОБЪЯСНИТЕ АНАЛИЗ

Merge Join  (cost=2003517.08..3623886.10 rows=1111500 width=37) (actual time=1834.616..29030.328 rows=61 loops=1)
  Merge Cond: (nearest_items.item_id = items_table.item_id)
  CTE nearest_items
    ->  Nested Loop  (cost=15731.91..1414499.28 rows=17150069 width=37) (actual time=24.501..30.230 rows=5562 loops=1)
          CTE nearest_restaurants
            ->  Gather  (cost=1956.86..15549.89 rows=1389 width=37) (actual time=0.729..24.410 rows=19 loops=1)
                  Workers Planned: 2
                  Workers Launched: 2
                  ->  Parallel Bitmap Heap Scan on places_table  (cost=956.86..14410.99 rows=579 width=37) (actual time=0.154..0.197 rows=6 loops=3)
                        Recheck Cond: ((geometry)::geography && '0101000020E61000008AE42B8194975DC02D776682E1F04040'::geography)
                        Filter: (('0101000020E61000008AE42B8194975DC02D776682E1F04040'::geography && _st_expand((geometry)::geography, '1500'::double precision)) AND _st_dwithin((geometry)::geography, '0101000020E61000008AE42B8194975DC02D776682E1F04040'::geography, '1500'::double precision, true))
                        Rows Removed by Filter: 3
                        Heap Blocks: exact=29
                        ->  Bitmap Index Scan on places_geometry_to_geography_index  (cost=0.00..956.51 rows=20831 width=0) (actual time=0.249..0.249 rows=29 loops=1)
                              Index Cond: ((geometry)::geography && '0101000020E61000008AE42B8194975DC02D776682E1F04040'::geography)
          ->  HashAggregate  (cost=31.25..33.25 rows=200 width=32) (actual time=24.446..24.458 rows=19 loops=1)
                Group Key: nearest_places.place_id
                ->  CTE Scan on nearest_places  (cost=0.00..27.78 rows=1389 width=32) (actual time=0.731..24.428 rows=19 loops=1)
          ->  Bitmap Heap Scan on items_table items_table_1  (cost=150.76..6975.28 rows=1930 width=74) (actual time=0.035..0.165 rows=293 loops=19)
                Recheck Cond: (place_id = nearest_places.place_id)
                Heap Blocks: exact=470
                ->  Bitmap Index Scan on items_table_place_id_index  (cost=0.00..150.28 rows=1930 width=0) (actual time=0.030..0.030 rows=293 loops=19)
                      Index Cond: (place_id = nearest_places.place_id)
  ->  Sort  (cost=589017.24..591795.99 rows=1111500 width=69) (actual time=117.743..117.810 rows=61 loops=1)
        Sort Key: items_table_index.item_id
        Sort Method: quicksort  Memory: 33kB
        ->  Nested Loop  (cost=385877.25..386217.98 rows=1111500 width=69) (actual time=39.721..117.632 rows=61 loops=1)
              ->  HashAggregate  (cost=385876.55..385878.55 rows=200 width=32) (actual time=36.690..39.319 rows=5562 loops=1)
                    Group Key: nearest_items.item_id
                    ->  CTE Scan on nearest_items  (cost=0.00..343001.38 rows=17150069 width=32) (actual time=24.504..33.625 rows=5562 loops=1)
              ->  Index Only Scan using items_table_index_pkey on itema_table_index  (cost=0.70..32.82 rows=32 width=37) (actual time=0.013..0.013 rows=0 loops=5562)
                    Index Cond: ((item_id = nearest_items.item_id) AND (key = 'medicine'::text))
                    Heap Fetches: 34
  ->  Index Only Scan using items_table_pkey on items_table  (cost=0.56..1517926.72 rows=34308144 width=37) (actual time=0.020..14910.737 rows=33838956 loops=1)
        Heap Fetches: 2567

Вот изображение, показывающее дизайн базы данных

https://ibb.co/GV8MpqV

Ожидаемый запрос

SELECT item_id
FROM item_tables
WHERE (ST_DWithin(places_table.geometry, ST_MakePoint(some_lon, some_lat)::geography, 1500))
  AND (
          (item_indexed_table.key = 'medicine')
       OR (item_indexed_table.key = 'potato' AND item_indexed_table.key = 'chips')
      )
  AND (items_color_table.color_id = 'f32nr-kfr32')
  • Простой английский:Выберите все идентификаторы предметов, которые находятся в радиусе вашего местоположения и содержат слово «лекарство» или слова «картофель» и «чип», а цветовой идентификатор равен «f32nr-kfr32»

ОжидаетсяРезультаты

  • список item_ids (должен быть в радиусе и должен иметь возможность фильтровать по цвету и ключу из других таблиц)
  • Мои таблицы очень большие, поэтому я бы хотелполучить время выполнения как можно меньше

Вотразмеры таблиц

placse_table: ~ 100000 строк

item_table: ~ 4000000 строк

item_index_table:> 100000000 строк

item_colors_table:> 1000000 строк

Я хотел бы любую помощь или советы, которые кто-нибудь может дать, Спасибо!

...