У меня есть база данных с последними данными о 400 000 точках по всему миру в одной таблице, а в другой таблице - около 1 миллиона человек. Каждое местоположение связано с одним человеком.
У меня есть сценарий php, который создает geojson из запроса bbox, и я хочу реализовать группировку / кластеризацию на стороне сервера, которая изменяется в зависимости от уровня масштабирования карты, передаваемого в сценарий.
В настоящее время мой запрос на 2-м уровне масштабирования (по существу, во всем мире) обычно имеет вид ...
SELECT lat, lon, count(locationId) as total
FROM locations
JOIN `people`
ON locations.personId=people.Id
WHERE MBRContains( GeomFromText( 'LINESTRING(-120 -61,120 60)' ), locations.point) // && other filters will be added here
GROUP BY concat(round(locations.lat,0),round(locations.lon,0))
ORDER BY `total` DESC
location.point имеет пространственный индекс. Я округляю лат и лон до количества десятичных знаков (и, следовательно, групп) в зависимости от уровня масштабирования.
Я обнаружил, что приведенный выше запрос теперь выполняется примерно за 3 секунды и возвращает чуть менее 1500 пунктов. Я хотел бы получить его менее чем за 1 секунду.
То, что я нашел, имело значение, чтобы добраться до этой цифры ...
- переключение с MyISAM на InnoDB (улучшение примерно в 3 раза)
- индексирование широты, долготы и точки вместе (улучшение примерно в 5 раз)
- уменьшение количества полей, которые я возвращал из таблицы
people
(небольшое улучшение)
- хотя я видел, что это было предложено в другом месте, конкат по значениям lat и lon, кажется, мало что меняет, если вообще что-либо имеет
- Я также попытался сгруппировать результаты по другому индексируемому отдельному столбцу в таблице местоположений, и он показывает только незначительное улучшение