2011-02-24 11 views
20

estoy tratando de resolver el problema de encontrar los vecinos más cercanos usando n PostGIS:Buscar n Vecinos más cercanos para un punto determinado usando PostGIS?

Punto de Partida: geoname

  • tabla con geonames (de geonames.org) que contiene latitud/longitud (WSG- 84)
  • añadido un geom GeometryColumn con srid = 4,326 y tipo de datos = punto de
  • geom Lleno de valores: geoname ACTUALIZACIÓN SET geom = ST_Se tSRID (ST_Point (longitud, latitud), 4326);
  • índice GIST Creado para geom (Crear geom_index ÍNDICE DE LA geoname USO GIST (geom);)/geom_index clúster: geom_index clúster en geoname;)
  • Creado PRIMARY KEY índice UNIQUE BTREE para geonameid

problema: Find n (por ejemplo, 5) vecinos más cercanos para un determinado punto en la tabla geoname representados por id (geoname.geonameid

Posible solución:.

Inspirado por http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor, probé la siguiente consulta: tiempo

"SELECT start.asciiname, ende.asciiname, distance_sphere(start.geom, ende.geom) as distance " + 
"FROM geoname As start, geoname As ende WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid " + 
"AND ST_DWithin(start.geom, ende.geom, 300) order by distance limit 5" 

de procesamiento: aproximadamente 60

también intentó un enfoque basado en EXPAND:

"SELECT start.asciiname, ende.asciiname, distance_sphere(start.geom, ende.geom) as distance " + 
"FROM geoname As start, geoname As ende WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid AND expand(start.geom, 300) && ende.geom " + 
"order by distance limit 5" 

Tiempo de ejecución: sobre 120s

La aplicación prevista es algún tipo de autocompletar. Por lo tanto, cualquier enfoque que tome más de> 1s no es aplicable. ¿Es generalmente posible lograr un tiempo de respuesta de < 1s con PostGIS?

+4

Creo que tienes una mejor oportunidad en http://gis.stackexchange.com/ para obtener una respuesta. –

Respuesta

39

Ahora ya PostGIS 2.0, hay un índice de KNN para este tipo de geometría disponibles. Esto le proporciona los 5 registros más cercanos sin tener en cuenta qué tan lejos están de "su ubicación ...".

SELECT * 
FROM your_table 
ORDER BY your_table.geom <-> "your location..." 
LIMIT 5; 

Ver <-> operador in PostgreSQL manual.

+0

¡Aseado! Una de las muchas cosas buenas que viene con la versión 2.0. Supongo que eso te dará resultados más rápido? ¿Sabes qué tipo de aceleración (aproximadamente) puedes esperar? – radek

+3

Solo para aclarar, el índice KNN se implementa realmente en PG> 9.1, así que asegúrese de tener instalada la versión adecuada de PG ... definitivamente vale la pena echarle un vistazo ... – Scholle

+0

También marcó esto como la respuesta porque probablemente sea la La forma más eficiente de hacer una búsqueda de un vecino más cercano utilizando la tecnología de db común ... – Scholle

6

Como creo que le respondieron en la lista, la unidad está en grados, por lo que busca casi todo el mundo con 300 grados en st_dwithin.

Si su conjunto de datos es tan grande, por lo que no puede trabajar en una proyección proyectada basada en el metro (cálculos mucho más rápidos y menos intensivos en la CPU) debería considerar utilizar el tipo geograpphy. Entonces puedes usar st_dwithin con el medidor.

Para que las cosas sean más rápidas, debería simplemente crear una nueva tabla con la geometría convertida a geografía.

Pero sólo probarlo se puede lanzar sobre la marcha:

SELECT start.asciiname, ende.asciiname, 
ST_Distance(start.geom::geography, ende.geom::geography) as distance 
FROM geoname As start, geoname As ende 
WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid AND 
ST_DWithin(start.geom::geography, ende.geom::geography, 300) 
order by distance 
limit 5; 

HTH Nicklas

Cuestiones relacionadas