Come implementare al meglio la ricerca del vicino più vicino in mysql?


10

Quindi, in breve,

  1. Quale dovrebbe essere il tipo di dati di latitudine e longitudine?
  2. Quale comando SQL dovrei chiamare per ottenere ad esempio i primi 100 ristoranti più vicini?

Dettaglio:

Ho 100k biz record ciascuno con latitudine e longitudine. Vedo che MySQL in realtà supporta un tipo di dati chiamato point. Dovrei usarlo invece?

MySQL supporta il sistema di archiviazione KDTree http://en.wikipedia.org/wiki/File:KDTree-animation.gif

È preferibile utilizzare il tipo di dati punto anziché il normale tipo di dati float per archiviare latitutude e longitudine?

Alla fine voglio trovare cose come i primi 100 ristoranti più vicini ai punti 105,6 per esempio e il mio database contiene molti biz e punti. Ovviamente calcolare la distanza uno per uno per ogni record e per ogni punto sarebbe O (n) e quindi fa schifo.

Si noti che sono a conoscenza di una soluzione più semplice descritta in Come un'applicazione come Yelp Recupera le informazioni sulla distanza dalla base di dati in modo efficiente e lo implementerò anch'io per iniziare. Questa è una buona risposta

Tuttavia, penso che ci sia una crema della risposta del raccolto che dovrebbe superare quella giusta? In effetti, archiviare la posizione in base alla latitudine e alla longitudine e trovare gli oggetti più vicini è un problema molto comune, mi aspetto che mysql abbia uno schema di progettazione speciale per questo. Ce l'ha?

Dove posso saperne di più? Grazie.



Sembra che la soluzione qui dba.stackexchange.com/questions/4210/… sia la soluzione migliore. Voglio dire, esiste una cosa chiamata MYSQL spaziale. Tuttavia non è possibile estrarre cose come where (distance (x) <20). Non è ancora implementato.
user4951

Risposte:


11

Per quanto riguarda i modelli di design, la domanda di Yelp è roba piuttosto standard.

Per una risposta più complessa, probabilmente avrai bisogno della distanza geospaziale. Ecco un affascinante powerpoint su questo argomento (e qui c'è anche una versione pdf di questo). Tuttavia, la matematica in questione è piuttosto brutta.

Dalla loro diapositiva:

set @orig_lat=122.4058; set @orig_lon=37.7907;
set @dist=10;

SELECT *, 3956 * 2 * ASIN(SQRT(
POWER(SIN((@orig_lat - abs(dest.lat)) * pi()/180 / 2), 2) +  COS(@orig_lat * pi()/180 ) * COS(abs(dest.lat) * pi()/180) *  POWER(SIN((@orig_lon  dest.lon) * pi()/180 / 2), 2) )) as  distance
FROM hotels dest 
having distance < @dist
ORDER BY distance limit 10

C'è una risposta più lunga e più approfondita sulla distanza geospaziale su Stack Overflow .

Ma vuoi comunque limitare i risultati per latitudine e longitudine.

Alla fine, eviterei il tipo di dati POINT e andrei con latitudine / longitudine. Al momento non c'è modo di determinare la distanza tra due PUNTI, quindi dovrai comunque memorizzare la latitudine / longitudine per quel calcolo.

Un ultimo collegamento: potresti anche voler dare un'occhiata a questo thread SO relativo all'accelerazione delle query utilizzando gli indici spaziali.


[ERRORE nella query 4] Si è verificato un errore nella sintassi SQL; controlla il manuale corrispondente alla versione del tuo server MySQL per la sintassi corretta da usare vicino a '- dest.lon) * pi () / 180/2), 2))) come distanza DA network_pos dest avente d' alla linea 2
Felipe

Ciao, @dist è sui mulini? grazie
Jorge Olaf Erlandsen il

1
@OlafErlandsen sì, è nel miglio
Jan van der Vegt,

4

I tipi di dati dei punti sono OK; puoi semplicemente invocare X (coord) / Y (coord) per ottenere i valori Lat / Lon.

Per esempio:

SELECT id, 
(3959 
    * acos(
        cos(radians(37)) 
        * cos(radians(Y(coord)))
        * cos(radians(X(coord)) - radians(-122)) 
        + sin(radians(37))
        * sin(radians(Y(coord)))
      )
) AS distance 
FROM markers HAVING distance < 25 
ORDER BY distance LIMIT 20;

37 è lat e -122 è lon? E 25 è metri o km?
Felipe,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.