Пространственный индекс PostgreSQL / PostGIS - без ускорения

15

У меня есть пространственная таблица в базе данных PostgreSQL / PostGIS. Каждая строка в нем представляет полигон. Это имеет следующую форму:

+----+--------+
|gid |   way  |
+----+--------+
|241 | 01030..|

Геометрический столбец - это «путь», который содержит геометрию для многоугольника. В WKT это: POLYGON (('....')). Я делаю много запросов ST_Contains к этой таблице, чтобы проверить, содержатся ли два полигона друг в друге, например:

Select ST_Contains(a.way, b.way) From table AS a, table AS b Where a.gid = 15 And b.gid = 16

Мне было интересно, как ускорить этот запрос и добавил пространственный индекс на таблицу:

CREATE INDEX table_way_gist ON table USING gist(way);

Но на самом деле я не вижу ускорения. Я создаю индекс ПОСЛЕ того, как я заполнил таблицу всеми полигонами ДО того, как я выполню запросы ST_Contains. Нужно ли добавлять индекс перед заполнением таблицы? Существуют ли специальные требования к таблице для работы с индексом? Проекция (srid) геометрического пути столбца установлена ​​в 900913.

Я использую: psql (PostgreSQL) 9.1.4 / POSTGIS = "1.5.3"

MichiMichbeck
источник

Ответы:

16

Наиболее эффективным индексом для запроса, выраженного в вашем вопросе, является индекс gid, поскольку это единственный столбец, который появляется в выражении where:

 CREATE INDEX table_gid ON table (gid);

Вы можете безопасно удалить гист-индекс, так как он будет занимать только место и медленно вставлять / обновлять / удалять вниз.

Длинное объяснение

Как я уже сказал, самый эффективный индекс в вашем случае - это индекс gid, поскольку он позволяет механизму БД быстрее извлекать строки (причем поиск обычно является самой медленной частью процесса). После этого он, вероятно, будет лучше вычислять результат

  ST_Contains(a.way, b.way)

Эспрессия, не глядя на указатель. Причина в том, что планировщик запросов, скорее всего, оценит, что дополнительные затраты на поиск индекса gist в обоих столбцах по сравнению с поиском значений a.way и b.way напрямую не стоят усилий, так как общее количество строк для поиска вероятно очень маленький, особенно если индекс уникален.

Как правило, помните, что планировщик, вероятно, предпочтет сканирование таблицы, а не сканирование индекса для небольших наборов данных (размеры наборов данных оцениваются с помощью статистики таблицы).

unicoletti
источник
Это делает проблему более ясной для меня. Я попробую. Так что, если я помещу запрос ST_Contains () в предложение WHERE, пространственный индекс должен быть полезен? Я думаю, что мне нужно реорганизовать мой скрипт для вызова ST_Contains в предложении WHERE. Сейчас я перебираю все полигоны и проверяю два из них по отдельности.
МичиМичбек
?? Вы понимаете, что пространственный индекс замедляет ход событий? Это новое для меня, потому что там, где я работаю, у нас есть пространственные индексы для каждой отдельной таблицы, и мне интересно, если это плохая практика
Luffydude
13

Как сказал unicoletti , суть индекса в столбце геометрии будет работать, только если вы используете ST_Contains () в выражении WHERE.

Например, если вы хотите знать все полигоны, которые содержат друг друга, вы можете использовать что-то вроде этого:

SELECT a.gid, b.gid
FROM table AS a, table as b
WHERE a.gid != b.gid and ST_Contains(a.way, b.way)

В этом случае, в зависимости от размера вашей таблицы и сложности ваших геометрий, индекс gist должен обеспечить значительное ускорение, так как ST_Contains начнет с фильтрации многоугольников, сравнивая их граничные блоки перед фактической проверкой их полной геометрии. Вы можете увидеть небольшое объяснение в учебнике OpenGeo .

Александр Нето
источник
Да, мне нужно, чтобы этот запрос включал проверку границы индекса. Спасибо Александр. (Я отмечу unicoletti как решение, так как он был быстр и прояснил проблему для меня)
MichiMichbeck