2010-10-19 16 views
1

J'ai une application qui a besoin d'interroger une table avec des coordonnées de latitude et de longitude, qui sont stockées en utilisant le type de données POINT de MYSQL.Façon d'améliorer les performances dans MySQL sur POINT (lat, long)

J'ai une fonction enregistrée qui trouve les lats et les longs proches dans un rayon donné d'un emplacement GPS donné. Cependant, ma table contiendra des centaines de milliers d'entrées, les performances doivent donc être optimales.

J'ai écrit la fonction stockée suivante, mais il faut environ 4,01 secondes pour renvoyer environ 9 000 lignes sur les 800 000 lignes possibles. Y a-t-il une meilleure façon de trouver les coordonnées GPS à proximité?

Voici ma fonction stockée:

CREATE PROCEDURE `FindNearbyPoints`(
    IN RADIUS FLOAT, 
    IN LAT FLOAT, 
    IN LON FLOAT 
) 
BEGIN 

    DECLARE EARTH_RADIUS FLOAT DEFAULT 3959; 
    DECLARE maxLat FLOAT DEFAULT (LAT + DEGREES(RADIUS/EARTH_RADIUS)); 
    DECLARE minLat FLOAT DEFAULT (LAT - DEGREES(RADIUS/EARTH_RADIUS)); 

    /* compensate for degrees longitude getting smaller with increasing latitude*/ 
    DECLARE maxLon FLOAT DEFAULT (LON + DEGREES(RADIUS/EARTH_RADIUS/COS(RADIANS(LAT)))); 
    DECLARE minLon FLOAT DEFAULT (LON - DEGREES(RADIUS/EARTH_RADIUS/COS(RADIANS(LAT)))); 

    SELECT *, acos(sin(LAT)*sin(radians(X(Location))) + cos(LAT)*cos(radians(X(Location)))*cos(radians(Y(Location))-LON))*EARTH_RADIUS As D 
    FROM (
     Select * 
     From my_table 
     Where X(Location)>minLat And X(Location)<maxLat 
     And Y(Location)>minLon And Y(Location)<maxLon 
    ) AS FIRST_CUT 
    WHERE acos(sin(LAT)*sin(X(Location)) + cos(LAT)*cos(X(Location))*cos(Y(Location)-LON))*EARTH_RADIUS < RADIUS 
    ORDER BY D; 

END 

Une grande partie de mon inspiration pour la fonction est provenu http://www.movable-type.co.uk/scripts/latlong-db.html

+0

Ma pensée naïve est que vous avez déjà de très bonnes performances. Je serai très intéressé de voir les suggestions pour l'améliorer. –

Répondre

0

Je ne sais pas comment votre base de données est mis en place, mais vous pourriez regarder dans Indexation SPATIAL, puis construction d'un rectangle de délimitation minimal pour effectuer la requête. Une fois que vous avez renvoyé des enregistrements via la boîte de délimitation, vous pouvez les commander rapidement à distance et éliminer ceux qui sont en dehors de votre rayon. Nous utilisons ce type d'indexation en génomique et interroge régulièrement des ensembles de données d'un milliard de lignes.

Il existe des détails sur l'indexation spatiale dans les documents mysql.