Estou tentando calcular algumas estatísticas para dados OSM usando o PostgreSQL 9.3.5 e o PostGIS 2.1.4. Comecei com um pequeno extrato de bavaria que baixei da Geofabrik. O esquema db é o esquema normal da API 0.6, os dados foram importados por meio da abordagem de despejo para o Postgres (usando os scripts pgsnapshot_schema_0.6 * .sql que vêm com osmose). ANALISAR O VÁCUO também foi realizado.
A única coisa personalizada que estou usando é uma tabela de polígonos que contém multipolígonos para todas as relações administrativas de limite. A geometria do polígono não foi simplificada de forma alguma.
O que estou tentando agora é contar todos os nós que estão dentro dos limites admin = 6 da bavaria. Aqui está minha consulta 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;
O tempo de execução dessa consulta é terrível porque o Postgres está fazendo uma junção de loop aninhada e varre todos os nós para todos os limites admin = 6. Para sua informação, a bavaria é dividida em 98 admin = 6 polígonos e existem cerca de 30 milhões de nós no extrato da bavaria.
É possível evitar essa execução subótima de consulta e informar ao Postgres que ele deve verificar todos os nós apenas uma vez (por exemplo, incrementando um contador para o polígono correspondente no conjunto de resultados ou usando dicas)?
Editar:
1) existe um índice espacial nos nós da bavaria:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2) o plano de consulta fica assim:
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)
Criei os dois índices a seguir, mas o plano de consulta (e o tempo de execução) não foram alterados
CREATE INDEX relpolygons_tags_boundary on bavaria.relpolygons( (tags->'boundary') );
CREATE INDEX relpolygons_tags_admin on bavaria.relpolygons( (tags->'admin_level') );
ANALYZE bavaria.relpolygons;
fonte
boundary
eadmin_level
) em colunas extras na tabela e use-as diretamente.Respostas:
A melhor maneira de indexar tags hstore é usar índices GIN ou GIST, que, a partir dos documentos , suportam @>,?,? & E | | operadores , isto é, procura chaves e pares chave / valor. A abordagem de usar uma função para extrair as tags para um índice da árvore B é razoável, mas como você também está checando pares específicos de chave / valor, o analisador escolheu uma varredura completa da tabela.
Não tenho acesso ao bavaria.relpolygons, mas com base em uma consulta semelhante para o OSM UK sobre limites de velocidade e tags de rodovia, recebo isso para minha explicação na consulta a seguir:
que mostra uma varredura direta de índice (usando o índice de essência), o que para uma tabela com 10 milhões de linhas é encorajador. O índice foi criado com o simples:
Embora eu não possa verificar sua condição espacial, acho que é menos seletivo do que
e, portanto, seria usado apenas para uma condição de verificação novamente.
Há também essa ótima resposta SO sobre a diferença entre os índices GIN e GIST . A conclusão geral é que os índices GIN, embora sejam maiores e mais lentos de compilar, são muito mais rápidos em problemas de recuperação de texto.
Lamento responder tão tarde, mas recentemente trabalho em semelhante OSM e hstore e descobri que não apenas uma vez estrelou esta pergunta, mas agora pude responder: D.
fonte