12 votos

Acelerar OpenStreetMap PostGIS consultar

Tengo datos OpenStreetMap para los países Bajos cargados en una base de datos PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) el uso de la ósmosis esquema. Esto significa que todas las etiquetas se almacenan en un hstore campo. Además de la ESENCIA índice que ósmosis crea en el campo de la geometría, he creado un adicional de GIST índice en el campo etiquetas.

Tratando de consulta utilizando tanto una limitación espacial y una restricción en el campo etiquetas, me parece 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));

dura 22 segundos para volver 78 los registros.

Existen alrededor de 53 millones de registros en esta tabla.

Es allí una manera de aumentar significativamente la velocidad de este proceso? He oído que hstore se implementa significativamente mejor en PostgreSQL 9, la actualización de la ayuda?

5voto

JimDaniel Puntos 4853

Usted puede tratar de crear un índice para su hstore columna,

CREATE INDEX nodes_tags_idx ON nodes USING GIST(tags)

y, a continuación, utilizar la ? operador para limitar la consulta sólo que las filas:

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'
  AND 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));

5voto

Captain Toad Puntos 396

Sería un método para consultar las etiquetas que usted está interesado en colocar los registros en una tabla nueva. A continuación, sólo necesita consultar la nueva tabla en lugar de todos los 53 millones de registros. Si usted está tratando de mantener su base de datos actualizada, usted podría tener esta consulta se ejecute cada vez que obtener nuevos datos de OSM.

3voto

Dwight T Puntos 544

El st_within y _st_within funciones no son conocidos por su velocidad. El && operador puede ayudar como se comprobará bbox en lugar de la geometría

Usted puede tratar el siguiente:

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'
  AND tags->'man_made'='surveillance' 
  AND geom && ST_SetSRID('BOX3D(4 52,5 53)'::box3d,4326);

Para obtener más consejos de rendimiento de verificación: http://postgis.refractions.net/docs/ch06.html

2voto

mde Puntos 186

El problema con tu consulta es el tags->'man_made'='surveillance' cláusula. Esto obliga a Postgres para ampliar las etiquetas hstore y no permite hacer uso del índice. Si reescribir esta usando @> (que contiene) se permitirá el uso de índices.

Debido a que usted está consultando un rectángulo, usted puede usar && en lugar de ST_Within. Esto va a tener una pequeña ganancia, como el ST_Within no es tan complicado de evaluar, y ST_Within implícitamente hace un && de verificación.

Un adicional de aumento de velocidad sería el uso de un GIN índice de etiquetas en lugar de un GIST índice. GIN índices de tomar más tiempo para construir, pero son más rápidos.

Toda la consulta 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 usted sabe que usted va a ser la consulta de una etiqueta en particular muchas cosas que usted puede crear un índice parcial en con 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' utilizar el índice. Por desgracia, ese índice no puede ayudar a @> de las consultas y el GIN o índices GIST no puede ayudar a tags->'foo' de las consultas, así que usted tiene que coincidir con el de las consultas a los índices que usted tiene.

1voto

dlanod Puntos 8661

pruebe esto en su lugar:

SELECCIONE n.geom,n.etiquetas,n.tstamp,u.nombre DE nodos n INNER JOIN usuarios COMO u n.user_id = u.id DONDE etiquetas @> 'man_made=>vigilancia'::hstore Y ST_Within(geom, ST_GeomFromText('POLÍGONO((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X