2009-02-09 17 views
6

Ho un elenco di record nel mio database e ogni record è associato a un codice postale.Qual è il modo migliore per interrogare un database per i record entro n miglia di un codice postale?

Qual è la "best practice" per interrogare tutti i record nel mio database per trovare tutte le voci che si trovano entro n miglia da un altro codice postale?

Ogni codice postale ha un lat/long associato ad esso nel database, quindi so che dovrò usarlo. Tuttavia, non riesco a immaginare di eseguire alcuna formula di distanza su ogni coppia di codici postali, convertendomi in miglia e rifiutando quelli che non rientrano nel mio raggio.

Sembra terribilmente computazionalmente costoso per una query così frequente.

Ho anche considerato di fare una pre-computazione di tutte le coppie ma sembra troppo grande da considerare anche. Ci sono circa ~ 40.000 codici postali negli Stati Uniti. Quindi, un database di tutte le coppie di ciascun codice postale sarebbe (40.000)^2 o 1,6 miliardi di voci.

So che questo è un problema comune sui siti Web, quindi spero che qualcuno possa indicarmi la direzione giusta per il modo migliore. Sto usando SQL Server 2008 e se ci sono soluzioni pre-costruite là fuori grandi allora, perché io davvero non voglio re-inventare la ruota in questa istanza.


questione connessa: Getting all zip codes within radius (questo non mi ha aiutato)
Inoltre, so di questo progetto SourceForge ma è abbandonato e non più in uso.

risposta

7

vorrei correre una query che ha restituito tutti i record tra parentesi nella busta quadrata encompasing il cerchio di ricerca radiale (minlat < lat < maxlat e minlong < lungo < maxlong), e poi post-process questo per restituire solo i punti all'interno del cerchio del raggio stesso. (Assicurarsi che i campi lat e long siano indicizzati).

Se si desidera ottenere fantasia, il server SQL supporta spatial indexes.

+0

dang: bastonatemi! –

0

Questo è in effetti un problema molto difficile da risolvere. Ti consiglierei di fare qualche imbroglio pre-creando un database. Crea una griglia di qualsiasi tipo di vicinanza che devi trovare, ad esempio, prendi ogni 10 miglia in ogni direzione, aggiungi una voce al database per ogni zip per quel punto della griglia e la distanza, e poi quando arriva una query, tu per prima cosa traduci il punto interrogativo in uno dei tuoi punti della griglia. Ora puoi guardare la distanza abbastanza facilmente.

Questa soluzione significa fondamentalmente lo scambio di spazio per il tempo, quindi è possibile ottenere rapidamente un database piuttosto grande. La buona notizia è che i dati sono molto facili da indicizzare.

+0

Un pre-computazione di tutte le coppie sarebbe un po 'grande. Aprox. 40.000 codici postali, quindi (40.000)^2 per ogni intervallo ci sarebbero un sacco di voci del database. – mmcdole

+0

Sarebbe aprox ~ 1,6 miliardi di voci per ogni intervallo ... Non so se sarebbe un'opzione. – mmcdole

+0

In realtà ciò che Ola Bini suggerisce è che è possibile ridurre notevolmente la quantità di voci se è possibile limitare la distanza massima tra i codici di avviamento postale (10 miglia nel suo esempio) – tehvan

3

corro a site that needs to run this query about once per second per user, ed ecco cosa ho imparato:

Prima di tutto, assicurarsi che il tavolo posizione ha indici su Lat e Lon. Questa è la differenza tra i tempi di risposta di 20ms e 15s se hai milioni di record.

Iniziare con una query del riquadro di delimitazione per ottenere un set di posizioni con cui lavorare. Quindi calcola le distanze su quelle, ordina, e se sei esigente riguardo alla precisione, filtrane alcune.

Francamente, non mi preoccuperei di pre-calcolare nulla.Come ho detto, eseguo questo tipo di query su una tabella di ubicazione con 6.000.000 di voci e in genere restituisce risultati in < 50 ms. A seconda delle esigenze, questo dovrebbe essere abbastanza veloce.

Buona fortuna!

+0

Grazie per le tue informazioni personali su questo problema. Lo apprezzo. – mmcdole

0

Si dovrebbe guardare GeoNames.org. Puoi richiedere il loro webservice per quello che stai cercando, oppure puoi dl il tuo database.