У меня есть данные OpenStreetMap для Нидерландов, загруженные в базу данных PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) с использованием схемы осмоса . Это означает, что все теги хранятся в поле hstore . В дополнение к индексу GIST, который осмос создает в поле геометрии, я создал дополнительный индекс GIST для поля тегов.
Пытаясь выполнить запрос, используя как пространственное ограничение, так и ограничение на поле тегов, я обнаружил, что это медленнее, чем хотелось бы. Запрос как этот:
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n
INNER JOIN users AS u ON n.user_id = u.id
WHERE tags->'man_made'='surveillance'
AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));
требуется 22 секунды, чтобы вернуть 78 записей.
В этой таблице около 53 миллионов записей.
Есть ли способ значительно ускорить это? Я слышал, что hstore реализован значительно лучше в PostgreSQL 9, поможет ли обновление?
Ответы:
Один из методов - запросить интересующие вас теги и поместить эти записи в новую таблицу. Тогда вам нужно будет только запросить новую таблицу вместо всех 53 миллионов записей. Если вы пытаетесь обновлять базу данных, этот запрос можно запускать каждый раз, когда вы получаете новые данные из OSM.
источник
Вы можете попытаться создать индекс для вашего столбца hstore,
а затем используйте
?
оператор, чтобы ограничить запрос только этими строками:источник
?
оператора занял 48 секунд по сравнению с 88 секундами для моего запроса (я не знаю, как я получил 72 секунды вчера, возможно, на этот раз машина выполняла что-то сложное, пока я выполнял запросы). Так что все еще не производительность, которую я ищу, но я получил более глубокое понимание того, как индексы GIST работают со столбцами hstore. Мне все еще придется пойти с другим решением создания материализованного представления, чтобы получить желаемую производительность.Функции st_within и _st_within не известны своей скоростью. Оператор && может помочь, так как он будет проверять bbox вместо геометрии
Вы можете попробовать следующее:
Для получения дополнительных советов по производительности проверьте: http://postgis.refractions.net/docs/ch06.html
источник
Проблема с вашим запросом заключается в
tags->'man_made'='surveillance'
предложении. Это вынуждает Postgres расширять теги hstore и не позволяет ему использовать индекс. Если переписать это с помощью@>
(содержит), это позволит использовать индекс.Поскольку вы запрашиваете прямоугольник, вы можете использовать
&&
вместо ST_Within. Это даст небольшой выигрыш, так как ST_Within не так сложно оценить, а ST_Within неявно выполняет&&
проверку.Дополнительным увеличением скорости было бы использование индекса GIN для тегов вместо индекса GIST. Создание индексов GIN занимает больше времени, но происходит быстрее.
Весь запрос будет
SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);
Если вы знаете, что будете часто запрашивать определенный тег, вы можете создать частичный индекс для него
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Это позволит условию WHERE
tags->'man_made'='surveillance'
использовать индекс. К сожалению, этот индекс не может помочь@>
запросам, а индексы GIN или GIST не могут помочьtags->'foo'
запросам, поэтому вы должны сопоставить запросы с имеющимися у вас индексами.источник
tags @>hstore()
значительно улучшили мой запрос, спасибо.попробуйте это вместо:
ВЫБЕРИТЕ n.geom, n.tags, n.tstamp, u.name ИЗ НОДОВ КАК n ВНУТРЕННИХ ПРИСОЕДИНИТЕЛЕЙ КАК ВКЛЮЧЕНО n.user_id = u.id ГДЕ теги @> 'man_made => Наблюдение' :: hstore AND ST_Within (geom , ST_GeomFromText ('POLYGON ((4,0 52,0,5,0 52,0,5,0 53,0,4,0 53,0,4,0 52,0))', 4326));
источник