ObjectManager, или как работать с большим количеством объектов на карте, Марина Степанова (Яндекс)
1. ObjectManager или как
работать с действительно
большим количеством
объектов на карте
Марина Степанова,
Яндекс
2. О чем поговорим
• Почему сложно показать много точек на
карте, обзор решений
• Как отрисовать большое количество меток на
клиенте
• Загрузка меток по требованию
• Организация хранения и обработки данных
на сервере
10. Очевидные недостатки
• page.html весит несколько Мб и страница
долго загружается
• Мы передаем на клиент слишком много
данных
• Мы рисуем на клиенте данные, которые
пользователь может не видеть
14. Решение №1 – активные области
Плюсы Минусы
Очень быстрый
рендеринг на клиенте
Оооочень сложная
серверная часть
Передаются только
данные для видимой
области
Клиентская картинка
абсолютно статична
16. Решение №2 – кластеризатор
Плюсы Минусы
Просто использовать Клиент тратит время на
кластеризацию
Дизайн определяется и
настраивается на
клиенте
Не решена проблема
оптимальной загрузки
данных
17. Решение №2 – кластеризатор
X 50 000
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
50 000
18. Решение №2 – кластеризатор
X 50 000
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
50 000
Лишние программные
инициализации
19. Что нужно в идеале?
• Никаких лишних инициализаций на
клиенте
• Запрашиваем данные пачками асинхронно
• Передаем на клиент только данные,
которые видит пользователь
• Рисуем на клиенте только данные, которые
видит пользователь
21. Храним только данные
• Все данные хранятся как их JSON-
описания в специальном менеджере
• Программные сущности создаются только
при необходимости нарисовать объект
22. X 50 000
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
new ymaps.Placemark([45.3, 25.45])
50 000
Храним только данные
29. Получился ObjectManager
• Хранит данные и не создает программные
сущности без надобности
• Мы вынесли всю инфраструктуру в общую
коллекцию, в метках оставили только самое
нужное
https://clck.ru/9LqPp
30. Время добавления на карту меток с
кластеризацией
6000
5000
4000
3000
2000
1000
0
1000 10000 50000
ObjectManager
Placemarks
34. Минусы подхода
• На малейший сдвиг нужно генерировать
новый запрос
• Многократная загрузка одних и тех же
данных
• Запросы всегда разные, непонятно, как
кешировать
37. Загружаем данные потайлово
• Данные загружаются всегда по одним и тем же
областям – легче организовать кеширование
• Запоминаем, какие тайлы подгружены, а
какие нет
• Небольшой сдвиг карты не вызывает
дозагрузку
38. RemoteObjectManager,
LoadingObjectManager
• Следят за видимой областью карты
• Следят, какие данные загружены, а какие еще нет
• Отправляют потайловые запросы за данными на
сервер
clck.ru/9Lp2J
clck.ru/9Lp2S
39. LoadingObjectManager
Загружает метки и кластеризует на
клиенте
RemoteObjectManager
Отвечает за загрузку и отображение
результатов серверной кластеризации
43. Генерация статических файлов
• Не требует сервера, отвечающего на запросы клиента
• Файлы могут занять очень много дискового
пространства
• Нужен скрипт, генерирующий эти файлы с некоторой
периодичностью
• Очень примитивное решение, подойдет для
небольших демо-проектов
50. Серверная кластеризация. v1
SELECT Id, long, lat,
FROM bigTable
WHERE latLon in bounds
1. Получаем данные для тайла из базы
2. Кластеризуем любым алгоритмом
3. Отправляем ответ на клиент
51. Серверная кластеризация. v1
Плюсы Минусы
Можно выбрать любой
алгоритм кластеризации
Чем красивее алгоритм,
тем дольше он работает
Нужно хорошо
организовать
кеширование ответа
54. Серверная кластеризация. v2
SELECT MIN(id) AS minId, COUNT(id) AS count, AVG(long)
AS long, AVG(lat) AS lat,
FLOOR( long/gridFactor) * gridFactor as gridX,
FLOOR( lat/gridFactor) * gridFactor AS gridY
FROM bigTable
WHERE latLon in bounds
GROUP BY gridX,gridY
Вместе с выборкой объектов сразу объединяем объекты в grid-кластеры
55. Серверная кластеризация. v2
Плюсы Минусы
Не надо писать
дополнительной логики
по кластеризации
Grid-кластеризация не
самая красивая
Быстро работает Ваша база данных вечно
считает, вы не
используете индексы
59. Серверная кластеризация. v3
БД
Отправка на
клиент
Данные, сгруппированные
по grid-кластерам
+ quadkey для каждой
точки
60. Серверная кластеризация. v3
SELECT MIN(id) AS minId, COUNT(id) AS count, AVG(long) AS long, AVG(lat) AS lat
FROM wiki
WHERE QuadCode between $Q1 and $Q2.
GROUP BY (QuadCode & $free)
Где:
free - маска «вариативности» хвоста.
free = 0xFFFFFFFF ^ (($Q2^$Q1)>>(2*gridFactor));
Q1,Q2 - диапазоны поиска QuadKey
Пример:
QuadCode: 320132321(base4), 9 знаков из 16(uint32)
Q1 : 320132321|0000000
Q2 : 320132321|3333333
free:333333333|3330000 (+3 зума, кластер 32х32)
61. Серверная кластеризация. v3
Плюсы Минусы
Очень быстро Grid-кластеризация не
самая красивая
Нужно заранее
насчитать Quad-коды
63. С кешированием все просто
• Поскольку запросы всегда потайловые, кешируем
ответ сервера для тайла на определенном зуме
• Пишите данные в файлы, используйте Memcached,
Redis и тд
• Если запрос поступает для большой тайловой
области, разбиваем его на отдельные тайлы и
собираем ответ из кеша потайлово
66. Опасный момент – обновление
данных
Загружены данные
старой версии
Сюда могут
подгрузиться данные
уже новой версии
67. Закладываем версионирование в
архитектуру
• Передаем на клиент версию данных
• Клиент всегда отправляет запросы с указанием версии
данных
• Храним несколько последних версий на сервере
• Системы кеширования тоже завязываем на версию
• Если нужно, продумываем автообновление версии на
клиенте
68. Полезные ссылки
• Работа с большим количеством объектов –
clck.ru/9Lp2e
• Если есть вопросы, пишите в клуб –
clubs.ya.ru/mapsapi/
69. Спасибо за внимание!
Марина Степанова,
руководитель группы разработки API
Яндекс.Карт
mstepanova@yandex-team.ru