2011-02-24 12 views
20

sto cercando di risolvere il problema di trovare i vicini n vicine usando PostGIS:Trova n Vicini più vicini per un determinato punto utilizzando PostGIS?

Punto di partenza:

  • Tavolo geoname con geonames (da geonames.org) contenente latitudine/longitudine (WSG- 84)
  • aggiunta una geom GeometryColumn con srid = 4326 e tipo di dati = PUNTO
  • geom Pieno di valori: UPDATE geoname SET geom = ST_Se tSRID (ST_Point (longitudine, latitudine), 4326);
  • Creato indice GIST per geom (CREATE INDEX geom_index ON geoname UTILIZZO GIST (geom);)/geom_index Clustered: CLUSTER geom_index ON geoname;)
  • Creato PRIMARY KEY indice UNIQUE BTREE per geonameid

problema: Find n (ad esempio 5) vicini più prossimi per un determinato punto nella tabella geoname rappresentate da id (geoname.geonameid

Possibile soluzione:.

Ispirato http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor, ho provato la seguente domanda: tempo

"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" 

Processing: circa 60s

anche cercato un approccio basato su 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" 

Tempo di lavorazione: circa 120s

L'applicazione prevista è una sorta di completamento automatico. Pertanto, qualsiasi approccio che richiede più di> 1 s non è applicabile. È generalmente possibile ottenere un tempo di risposta di < 1s con PostGIS?

+4

Penso che tu abbia una migliore possibilità su http://gis.stackexchange.com/ per ottenere una risposta. –

risposta

39

Ora, poiché PostGIS 2.0, c'è un indice di KNN per i tipi di geometria disponibili. Questo ti dà 5 record più vicino ignorare quanto lontano sono lontano da "la tua posizione ...".

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

Vedi <-> operatore in PostgreSQL manual.

+0

Neat! Una delle tante chicche in arrivo con la versione 2.0. Suppongo che ti daranno risultati più velocemente? Sai che (approssimativamente) tipo di accelerazione puoi aspettarti? – radek

+3

Giusto per chiarire, l'indice KNN è attualmente implementato in PG> 9.1, quindi assicuratevi di avere la versione corretta del PG installato ... vale sicuramente la pena di verificarlo ... – Scholle

+0

Anche contrassegnato come risposta perché è probabilmente il il modo più efficiente di eseguire una ricerca per il vicinato più vicino utilizzando la tecnologia db comune ... – Scholle

6

Siccome penso che tu abbia risposto alla lista, l'unità è in gradi, quindi stai cercando quasi il mondo intero con 300 gradi in st_dwithin.

Se il set di dati è così grande che non è possibile lavorare in una proiezione meterbata proiettata (calcoli molto più veloci e meno intensivi della CPU), si dovrebbe prendere in considerazione l'uso del tipo di geografico. Quindi puoi usare st_dwithin con meter.

Per rendere le cose più veloci dovrei creare una nuova tabella con la geometria convertita in geografia.

Ma a poco testarlo si può lanciare al volo:

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

Problemi correlati