По необходимости и TFS являются единственными опциями, о которых я знаю. Я знаю, что они оба использовались на крупномасштабных проектах в Microsoft. Хранилище может масштаб, настолько большой, но я не знаю, идет ли это вне 500-1000 пользователей.
Здесь есть хороший документ о производительности геолокации MySQL .
РЕДАКТИРОВАТЬ Я уверен, что здесь используется фиксированный радиус. Кроме того, я не на 100% уверен, что алгоритм вычисления расстояния является наиболее продвинутым (то есть он будет «просверливать» Землю).
Важно то, что этот алгоритм дешев, чтобы дать вам ограничение на количество мячей. строк для правильного поиска расстояния.
Алгоритм предварительно фильтрует, выбирая кандидатов в квадрате вокруг исходной точки, а затем вычисляя расстояние в милях .
Предварительно вычислите это или используйте хранимая процедура, как предлагает источник:
# Pseudo code
# user_lon and user_lat are the source longitude and latitude
# radius is the radius where you want to search
lon_distance = radius / abs(cos(radians(user_lat))*69);
min_lon = user_lon - lon_distance;
max_lon = user_lon + lon_distance;
min_lat = user_lat - (radius / 69);
max_lat = user_lat + (radius / 69);
SELECT dest.*,
3956 * 2 * ASIN(
SQRT(
POWER(
SIN(
(user_lat - dest.lat) * pi() / 180 / 2
), 2
) + COS(
user_lat * pi() / 180
) * COS(
dest.lat * pi() / 180
) * POWER(
SIN(
(user_lon - dest.lon) * pi() / 180 / 2
), 2
)
)
) as distance
FROM dest
WHERE
dest.lon between min_lon and max_lon AND
dest.lat between min_lat and max_lat
HAVING distance < radius
ORDER BY distance
LIMIT 10
Если вам действительно нужно повысить производительность, вы можете определить ограничивающие рамки для ваших данных и сопоставьте предварительно вычисленные ограничивающие прямоугольники с вашими объектами при вставке и используйте их позже для запросов.
Если наборы результатов достаточно малы, вы все равно можете вносить корректировки точности в логику приложения (проще масштабировать по горизонтали, чем базу данных), позволяя выдавать точные результаты.
Взгляните на Брета Слаткина geobox.py , который содержит отличную документацию по этому подходу.
Я все же рекомендую проверить PostgreSQL и PostGIS по сравнению с MySQL, если вы планируете выполнять более сложные запросы в обозримом будущем.
У меня была та же проблема, и я написал пост в блоге из 3 частей. Это было быстрее, чем географический индекс.
Индексы, которые вы используете, действительно являются индексами B-дерева и поддерживают ключевое слово BETWEEN
в вашем запросе. Это означает, что оптимизатор может использовать ваши индексы для поиска домов в вашем «ящике». Однако это не означает, что он всегда будет использовать индексы. Если вы укажете диапазон, содержащий слишком много "совпадений", индексы не будут использоваться.
Это выглядит довольно быстро. Меня беспокоит только то, что он будет использовать индекс для получения всех значений в пределах 3 миль от широты, а затем фильтровать их для значений в пределах 3 миль от долготы. Если я понимаю, как работает базовая система, вы можете использовать только один ИНДЕКС для каждой таблицы, поэтому индекс по широте или долготе бесполезен.
Если у вас большой объем данных, он может ускорить вещи, чтобы дать каждому квадрату 1x1 мили уникальный логический идентификатор, а затем сделать дополнительное ограничение на SELECT, которое (area = "23234/34234" OR area = "23235/34234" OR ...) для всех квадратов вокруг вашего point, затем заставьте базу данных использовать этот индекс, а не широту и долготу. Тогда вы будете фильтровать гораздо меньше квадратных миль данных.
Дома? У вас их, наверное, не будет даже десяти тысяч. Просто используйте индекс в памяти, например STRTree .
Придерживаясь вашего текущего подхода, вы должны сделать одно изменение, Вместо того чтобы индексировать геолокацию и геолонг по отдельности, вы должны иметь составной индекс:
KEY `geolat_geolng` (`geolat`, `geolng`),
В настоящее время ваш запрос будет использовать только один из двух индексов.