sql >> Database >  >> RDS >> Mysql

MYSQL Geo Search met prestaties op afstand

De snelste manier om dit te doen, is door de geospatiale extensies voor MySQL te gebruiken, wat eenvoudig genoeg zou moeten zijn omdat u al een MyISAM-tabel gebruikt. De documentatie voor deze extensies is hier te vinden:http:/ /dev.mysql.com/doc/refman/5.6/en/spatial-extensions.html

Voeg een nieuwe kolom toe met een POINT-gegevenstype:

ALTER TABLE `adverts` 
ADD COLUMN `geopoint` POINT NOT NULL AFTER `longitude`
ADD SPATIAL KEY `geopoint` (`geopoint`)

U kunt deze kolom vervolgens vullen vanuit uw bestaande velden voor breedtegraad en lengtegraad:

UPDATE `adverts` 
SET `geopoint` = GeomFromText(CONCAT('POINT(',`latitude`,' ',`longitude`,')'));

De volgende stap is het maken van een begrenzingsvak op basis van de invoerbreedte- en lengtegraad die zal worden gebruikt in uw WHERE clausule als een CONTAINS beperking. U moet een set van X,Y POINT . bepalen coördinaten die voor uw vereisten werken op basis van het gewenste zoekgebied en het gegeven startpunt.

Uw laatste zoekopdracht zoekt naar alle POINT gegevens binnen uw zoekopdracht POLYGON , en u kunt vervolgens een afstandsberekening gebruiken om uw gegevens verder te verfijnen en te sorteren:

SELECT a.*, 
    ROUND( SQRT( ( ( (adverts.latitude - '53.410778') * (adverts.latitude - '53.410778') ) * 69.1 * 69.1 ) + ( (adverts.longitude - '-2.97784') * (adverts.longitude - '-2.97784') * 53 * 53 ) ), 1 ) AS distance
FROM adverts a
WHERE a.type_id = 3
AND CONTAINS(a.geopoint, GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'))
HAVING distance < 25
ORDER BY distance DESC
LIMIT 0, 30

Merk op dat de GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))') in het bovenstaande zal niet werken , moet u de coördinaten vervangen door geldige punten rond uw zoekstart. Als u verwacht dat de lat/long zal veranderen, kunt u overwegen een trigger te gebruiken om de POINT te behouden. gegevens en bijbehorende SPATIAL KEY bijgewerkt. Met grote datasets zou u enorm verbeterde prestaties moeten zien ten opzichte van het berekenen van een afstand voor elk record en filteren met behulp van een HAVING clausule. Ik heb persoonlijk functies gedefinieerd voor gebruik bij het bepalen van de afstand en het maken van de begrenzende POLYGON .



  1. Slaapstand-fouten in benoemde zoekopdrachten

  2. doctrine2 - Hoe de spoelefficiëntie verbeteren?

  3. De aggregatie-operator voor vermenigvuldiging in SQL

  4. Varchar-probleem op Mysql 2147483647