Problemet er, at den måde, du gemmer data på i databasen, ikke er egnet til den type opgave, du udfører. Brug af Point
værdier i Geometry
datapunkter er vejen at gå. Faktisk kodet noget 4+ år tilbage til dette formål, men har problemer med at finde det. Men dette indlæg synes at dække det godt.
REDIGER Okay, fandt min gamle kode, men den henviser til gamle klientdata, som jeg åbenbart ikke kan dele. Men nøglen til hastighed med koordinater i databaser er at bruge POINT
data gemt i databasetabellen med typen GEOMETRY
. Flere detaljer her
på den officielle MySQL-side. Da jeg i et stykke tid har haft brug for en grund til at gense denne type kode – og koncepterne – er her et hurtigt MySQL-script, jeg har lavet en prøvetabel med eksempeldata for at formidle de grundlæggende koncepter. Når du først forstår, hvad der sker, åbner det op for mange fede muligheder.
Fandt også denne gode/enkle forklaring også af konceptet.
Og fandt en anden stor vurdering af geografiske data i MySQL 5.6. Masser af god information om indekser og ydeevne. Specifikt vedrørende MySQL rumlige indeksydelse:
Og på den anden side af det:
Og her er mine grundlæggende MySQL-testscripts for at hjælpe med at illustrere konceptet:
/* 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
;