Большая база данных MySQL (21MM записей) с данными о местоположении - каждое местоположение имеет широту и длину - необходимо выполнить запрос «рядом» - PullRequest
1 голос
/ 29 июля 2011

У нас есть большая база данных местоположения - для каждой строки указывается lat long.БД размещается в MySQL.

Нам нужно выполнить два типа запросов:

  • места поблизости (сортировка по расстоянию)
  • места поблизости по категории (гдекатегория - это столбец)

По мере роста количества записей этот запрос резко замедляется.

SELECT *, ( 3959 * acos( cos( radians(40.759105) ) * cos( radians( Latitude ) ) * cos( radians( longitude) - radians(-73.984654) ) + sin( radians(40.759105) ) * sin( radians( Latitude ) ) ) ) as distance FROM mcw_in WHERE Latitude <> '' ORDER BY distance LIMIT 0,20

Как создать индекс в MySQL для устранения медлительности?Есть ли какое-либо другое решение, например, использование любых типов геопространственных данных?

Ответы [ 3 ]

0 голосов
/ 06 сентября 2013

Лучше использовать запросы диапазона, определив ограничивающий прямоугольник вокруг центра.Следующий запрос выполняет поиск в ближайших 20 местоположениях на расстоянии $ dist от центра ($ lat0, $ lng0), а результат сортируется по расстоянию.Вам нужны два индекса, один на «lat» и один на «lng».Некоторые объяснения можно найти здесь .

SELECT *,
    ( 6371 * acos(
    cos(radians($lat0)) * cos(radians(lat)) * cos(radians(lng) - radians($lng0)) +
    sin(radians($lat0)) * sin(radians(lat))
    ) ) AS distance
FROM `locations`
WHERE lat < degrees( asin( sin(radians($lat0)) * cos($dist / 6371) +
        cos(radians($lat0)) * sin($dist / 6371) * cos(radians(0)) ))
  AND lat > degrees( asin( sin(radians($lat0)) * cos($dist / 6371) +
        cos(radians($lat0)) * sin($dist / 6371) * cos(radians(180)) ))
  AND lng < $lng0 - degrees( atan2(sin(radians(90)) * sin(radians($dist / 6371)) * cos(radians($lat0)),
        cos(radians($dist / 6371)) - sin(radians($lat0)) * sin(radians($lat0))) )
  AND lng > $lng0 + degrees( atan2(sin(radians(90)) * sin(radians($dist / 6371)) * cos(radians($lat0)),
        cos(radians($dist / 6371)) - sin(radians($lat0)) * sin(radians($lat0))) )
ORDER BY distance LIMIT 20;
0 голосов
/ 07 августа 2011

Но на самом деле это не будет работать в MySQL, так как они на самом деле не реализовали функции.

Если вы открыты для этого, я бы рекомендовал использовать PostGIS или Spatialiate (работающий на Postgresql и SQLLite соответственно) или даже mongodb или geocouch.Они имеют гораздо больший набор реализованных пространственных функций.Если вы посмотрите на документацию MySQL, то в основном говорится, что она «не реализована» для пространственных функций.

...