Комбінований ключ / значення Hstore та просторовий запит занадто повільні, щоб обробляти більші витяги з OSM


13

Я намагаюся обчислити деяку статистику для даних OSM за допомогою PostgreSQL 9.3.5 та PostGIS 2.1.4. Я почав з невеликого екстракту баварії, який я завантажив з Geofabrik. Схема db - це звичайна схема API 0.6, дані були імпортовані за допомогою дамп-підходу до Postgres (використовуючи сценарії pgsnapshot_schema_0.6 * .sql, які поставляються з осмосом). АНАЛІЗОВИЙ ВАКУУМ також був виконаний.

Єдине, що я використовую на замовлення, - це полігонна таблиця, яка містить багатополігони для всіх адміністративних граничних відносин. Геометрію багатокутника жодним чином не спрощували.

Зараз я намагаюся досягти підрахунку всіх вузлів, які знаходяться всередині адміністратора = 6 меж баварії. Ось мій запит SQL:

SELECT relpoly.id, count(node) 
FROM bavaria.relpolygons relpoly, bavaria.nodes node
WHERE relpoly.tags @> '"boundary"=>"administrative","admin_level"=>"6"'::hstore 
AND ST_Intersects(relpoly.geom, node.geom)
GROUP BY relpoly.id;

Виконання цього запиту жахливе, оскільки Postgres робить вкладений цикл з'єднання та сканує всі вузли для кожного адміністратора = 6 кордонів. Здійснюється, баварія ділиться на 98 адмін = 6 полігонів і в екстракті баварії є близько 30 мільйонів вузлів.

Чи можна уникнути цього неоптимального виконання запиту і сказати Postgres, що він повинен сканувати всі вузли лише один раз (наприклад, збільшенням лічильника для відповідного багатокутника в наборі результатів або за допомогою підказки)?

Редагувати:

1) просторовий індекс існує на вузлах баварії:

CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);

2) план запитів виглядає так:

HashAggregate  (cost=284908.49..284908.75 rows=26 width=103)
  ->  Nested Loop  (cost=111.27..283900.80 rows=201537 width=103)
        ->  Bitmap Heap Scan on relpolygons relpoly  (cost=4.48..102.29 rows=26 width=5886)
              Recheck Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
              ->  Bitmap Index Scan on relpolygons_geom_tags  (cost=0.00..4.47 rows=26 width=0)
                    Index Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
        ->  Bitmap Heap Scan on nodes node  (cost=106.79..10905.50 rows=983 width=127)
              Recheck Cond: (relpoly.geom && geom)
              Filter: _st_intersects(relpoly.geom, geom)
              ->  Bitmap Index Scan on idx_nodes_geom  (cost=0.00..106.55 rows=2950 width=0)
                    Index Cond: (relpoly.geom && geom)

3)

Я створив наступні два індекси, але план запитів (і час виконання) не змінився

CREATE INDEX relpolygons_tags_boundary on bavaria.relpolygons( (tags->'boundary') );
CREATE INDEX relpolygons_tags_admin on bavaria.relpolygons( (tags->'admin_level') );
ANALYZE bavaria.relpolygons;

1
У вас є просторовий індекс у bavaria.nodes?
користувач30184

так, я відредагував питання та надав інформацію про індекс на вузлах та план запитів
Альф Кортіг,

3
Два варіанти. 1 - додайте індекс для тегів hstore. 2 - витягніть теги, які ви використовуєте для запиту ( boundaryі admin_level), у зайві стовпці таблиці та використовуйте їх безпосередньо.
BradHards

Див. Редагування (3): додано два індекси, але не було змінено план запитів, а також час виконання.
Альф Кортіг

Після деяких тестувань я вже не впевнений, чи створив правильні індекси в (3). Поки мені вдалося створити індекс для -> і? оператори магазину. Однак я використовую @> у своєму запиті
Альф Кортіг,

Відповіді:


5

Найкращий спосіб індексувати теги hstore - це використання індексів GIN або GIST, які з документів підтримують @>,?,? І? | оператори , тобто здійснюють пошук по клавішах і парі ключів / значень. Ви підходите до використання функції для вилучення тегів для індексу B-дерева розумно, але оскільки ви також перевіряєте наявність конкретних пар ключ / значення, аналізатор обрав повне сканування таблиці.

У мене немає доступу до bavaria.relpolygons, але грунтуючись на подібному запиті для OSM UK щодо обмежень швидкості та тегів шосе, я отримую це для пояснення у наступному запиті:

SELECT count(*) 
 FROM ways 
WHERE tags @> 'highway=>motorway'::hstore 
 AND tags @> 'maxspeed=>"50 mph"'::hstore;


Aggregate  (cost=48.66..48.67 rows=1 width=0)
    ->  Index Scan using ix_ways_tags_gist on ways  (cost=0.42..48.64 rows=11 width=0)
     Index Cond: ((tags @> '"highway"=>"motorway"'::hstore) AND (tags @> '"maxspeed"=>"50 mph"'::hstore))

який показує пряме сканування індексу (з використанням індексу суті), що для таблиці з 10 мільйонами рядків є обнадійливим. Індекс створений простим:

CREATE INDEX ix_ways_tags_gist ON ways USING gist (tags);

Хоча я не можу перевірити ваш просторовий стан, я гадаю, що він менш вибірковий, ніж

ДЕ relpoly.tags @> '"межа" => "адміністративний", "admin_level" => "6"' :: hstore.

і тому буде використовуватися лише для умови повторної перевірки.

Існує також ця чудова відповідь на різницю між індексами GIN та GIST . Загальне висновок полягає в тому, що індекси GIN, хоча вони збільшуються та повільніші, значно швидше вирішують проблеми пошуку тексту.

Вибачте, що відповідаю так пізно, але останнім часом я займаюся подібною роботою над OSM та hstore, і виявив, що не тільки колись зірвав це питання, але і тепер міг відповісти на нього: D.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.