Eu tenho dados do OpenStreetMap para a Holanda carregados em um banco de dados PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) usando o esquema de osmose . Isso significa que todas as tags são armazenadas em um campo hstore . Além do índice GIST que a osmose cria no campo geometria, criei um índice GIST adicional no campo tags.
Tentando consultar usando uma restrição espacial e uma restrição no campo tags, acho que é mais lento do que gostaria. Uma consulta como esta:
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));
leva 22 segundos para retornar 78 registros.
Existem cerca de 53 milhões de registros nesta tabela.
Existe uma maneira de acelerar significativamente isso? Ouvi dizer que o hstore é implementado significativamente melhor no PostgreSQL 9. A atualização ajudaria?
Respostas:
Um método seria consultar as tags de seu interesse e colocar esses registros em uma nova tabela. Então, você só precisará consultar a nova tabela em vez de todos os 53 milhões de registros. Se você está tentando manter seu banco de dados atualizado, essa consulta pode ser executada toda vez que você obtiver novos dados do OSM.
fonte
Você pode tentar criar um índice para sua coluna hstore,
e use o
?
operador para limitar a consulta apenas a essas linhas:fonte
?
operador levou 48 segundos em comparação com 88 segundos para a minha consulta (não sei como recebi 72 segundos ontem, talvez a máquina estivesse fazendo algo complicado dessa vez enquanto eu realizava as consultas). Portanto, ainda não o desempenho que estou procurando, mas adquiri uma compreensão mais profunda de como os índices GIST operam nas colunas hstore. Ainda terei que ir com a outra solução de criar uma visão materializada para obter o desempenho que desejo.As funções st_within e _st_within não são conhecidas por sua velocidade. O operador && pode ajudar, pois verifica a bbox em vez da geometria
Você pode tentar o seguinte:
Para obter mais dicas de desempenho, verifique: http://postgis.refractions.net/docs/ch06.html
fonte
O problema com sua consulta é a
tags->'man_made'='surveillance'
cláusula Isso força o Postgres a expandir as tags hstore e não permite que ele faça uso do índice. Se você reescrever isso usando@>
(contém), permitirá o uso do índice.Como você está consultando um retângulo, pode usar em
&&
vez de ST_Within. Isso terá um pequeno ganho, pois o ST_Within não é tão complicado de avaliar e o ST_Within faz uma&&
verificação implicitamente .Um aumento de velocidade adicional seria usar um índice GIN em tags, em vez de um índice GIST. Os índices GIN levam mais tempo para criar, mas são mais rápidos.
Toda a consulta seria
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);
Se você sabe que consultará muito uma determinada tag, poderá criar um índice parcial nela
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Isso permitirá que a condição WHERE
tags->'man_made'='surveillance'
use o índice. Infelizmente, esse índice não pode ajudar as@>
consultas e os índices GIN ou GIST não podem ajudar astags->'foo'
consultas, portanto, você deve corresponder as consultas aos índices existentes.fonte
tags @>hstore()
maciçamente melhorou minha consulta, obrigado.tente isso:
SELECT n.geom, n.tags, n.tstamp, u.name FROM nós COMO n INTERESSE ENTRE usuários COMO u ON n.user_id = u.id WHERE tags @> 'man_made => surveillance' :: 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));
fonte