Tengo datos de OpenStreetMap para los Países Bajos cargados en una base de datos PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) usando el esquema de ósmosis . Esto significa que todas las etiquetas se almacenan en un campo hstore . Además del índice GIST que crea la ósmosis en el campo de geometría, creé un índice GIST adicional en el campo de etiquetas.
Intentando consultar usando una restricción espacial y una restricción en el campo de etiquetas, encuentro que es más lento de lo que me gustaría. Una 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));
Tarda 22 segundos en devolver 78 registros.
Hay alrededor de 53 millones de registros en esta tabla.
¿Hay alguna manera de acelerar significativamente esto? He oído que hstore se implementa significativamente mejor en PostgreSQL 9, ¿ayudaría la actualización?
Respuestas:
Un método sería consultar las etiquetas que le interesan y colocar esos registros en una nueva tabla. Luego, solo tendrá que consultar la nueva tabla en lugar de los 53 millones de registros. Si está intentando mantener actualizada su base de datos, puede hacer que se ejecute esta consulta cada vez que obtenga datos nuevos de OSM.
fuente
Puede intentar crear un índice para su columna hstore,
y luego use el
?
operador para limitar la consulta solo a esas filas:fuente
?
operador tomó 48 segundos en comparación con 88 segundos para mi consulta (no sé cómo obtuve 72 segundos ayer, tal vez la máquina estaba haciendo algo complicado esta vez mientras realizaba las consultas). Entonces todavía no es el rendimiento que estoy buscando, pero obtuve una comprensión más profunda de cómo funcionan los índices GIST en las columnas de hstore. Todavía tendré que ir con la otra solución de crear una vista materializada para obtener el rendimiento que quiero.Las funciones st_within y _st_within no son conocidas por su velocidad. El operador && podría ayudar, ya que marcará bbox en lugar de geometría
Puede intentar lo siguiente:
Para obtener más consejos de rendimiento, consulte: http://postgis.refractions.net/docs/ch06.html
fuente
El problema con su consulta es la
tags->'man_made'='surveillance'
cláusula. Esto obliga a Postgres a expandir las etiquetas hstore y no le permite hacer uso del índice. Si reescribe esto usando@>
(contiene), permitirá el uso del índice.Debido a que está consultando un rectángulo, puede usarlo en
&&
lugar de ST_Within. Esto tendrá una pequeña ganancia, ya que ST_Within no es tan complicado de evaluar, y ST_Within implícitamente hace una&&
comprobación.Un aumento de velocidad adicional sería usar un índice GIN en las etiquetas en lugar de un índice GIST. Los índices GIN tardan más en construirse pero son más rápidos.
La consulta completa sería
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);
Si sabe que va a consultar mucho una etiqueta en particular, puede crear un índice parcial con ella
CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);
.Esto permitirá que la condición WHERE
tags->'man_made'='surveillance'
use el índice. Desafortunadamente, ese índice no puede ayudar a las@>
consultas y los índices GIN o GIST no pueden ayudar a lastags->'foo'
consultas, por lo que debe hacer coincidir las consultas con los índices que tiene.fuente
tags @>hstore()
masivamente mejoró mi consulta, gracias.intente esto en su lugar:
SELECCIONE n.geom, n.tags, n.tstamp, u.name DESDE los nodos COMO n INTERIOR ÚNASE a los usuarios AS u ON n.user_id = u.id DONDE etiquetas @> 'man_made => vigilancia' :: hstore Y 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));
fuente