Het probleem is dat de manier waarop u gegevens in de database opslaat, niet geschikt is voor het soort taak dat u uitvoert. Point
gebruiken waarden in Geometry
datapunten is de juiste keuze. Eigenlijk iets van 4+ jaar geleden voor dit doel gecodeerd, maar problemen om het te vinden. Maar dit bericht lijkt het goed te dekken.
BEWERKEN Oké, ik heb mijn oude code gevonden, maar die verwijst naar oude klantgegevens die ik natuurlijk niet kan delen. Maar de sleutel tot snelheid met coördinaten in databases is het gebruik van POINT
gegevens opgeslagen in de databasetabel met het type GEOMETRY
. Meer details hier
op de officiële MySQL-site. Omdat ik een reden nodig had om dit type code - en de concepten - een tijdje opnieuw te bekijken, is hier een snel MySQL-script dat ik heb gemaakt om een voorbeeldtabel te maken met voorbeeldgegevens om de basisconcepten over te brengen. Als je eenmaal begrijpt wat er aan de hand is, ontstaan er veel coole opties.
Vond ook deze geweldige/eenvoudige uitleg ook van het concept.
En vond nog een geweldige beoordeling van ruimtelijke gegevens in MySQL 5.6. Veel geweldige informatie over indexen en prestaties. Specifiek met betrekking tot de prestaties van de ruimtelijke index van MySQL:
En aan de andere kant:
En hier zijn mijn basis MySQL-testscripts om het concept te illustreren:
/* Create the database `spatial_test` */
CREATE DATABASE `spatial_test` CHARACTER SET utf8 COLLATE utf8_general_ci;
/* Create the table `locations` in `spatial_test` */
CREATE TABLE `spatial_test`.`locations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`coordinates` point NOT NULL,
UNIQUE KEY `id` (`id`),
SPATIAL KEY `idx_coordinates` (`coordinates`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
/* Insert some test data into it. */
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.174961 78.041822)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.985818 86.923596)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(44.427963 -110.588455)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(19.896766 -155.582782)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.748328 -73.985560)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.782710 -73.965310)'));
/* A sample SELECT query that extracts the 'latitude' & 'longitude' */
SELECT x(`spatial_test`.`locations`.`coordinates`) AS latitude, y(`spatial_test`.`locations`.`coordinates`) AS longitude FROM `spatial_test`.`locations`;
/* Another sample SELECT query calculates distance of all items in database based on GLength using another set of coordinates. */
SELECT GLength(LineStringFromWKB(LineString(GeomFromText(astext(PointFromWKB(`spatial_test`.`locations`.`coordinates`))), GeomFromText(astext(PointFromWKB(POINT(40.782710,-73.965310))))))) AS distance
FROM `spatial_test`.`locations`
;
/* Yet another sample SELECT query that selects items by using the Earth’s radius. The 'HAVING distance < 100' equates to a distance of less than 100 miles or kilometers based on what you set the query for. */
/* Earth’s diameter in kilometers: 6371 */
/* Earth’s diameter in miles: 3959 */
SELECT id, (3959 * acos(cos(radians(40.782710)) * cos(radians(x(`spatial_test`.`locations`.`coordinates`))) * cos(radians(y(`spatial_test`.`locations`.`coordinates`)) - radians(-73.965310)) + sin(radians(40.782710)) * sin(radians(x(`spatial_test`.`locations`.`coordinates`))))) AS distance
FROM `spatial_test`.`locations`
HAVING distance < 100
ORDER BY id
;