
Apache Superset — востребованное open-source решение для анализа данных, которое можно быстро установить и встроить в существующий технологический стек компании, благодаря большому количеству коннекторов и видов визуализаций. Однако для высоконагруженных систем и сложных сценариев некоторые компании дорабатывают исходную версию — например, внедряют инструменты автоматического кеширования и оптимизируют архитектуру хранения данных для построения графиков. По этому пути в своё время пошли и мы в VK.
Привет, Хабр. Меня зовут Никита Романов. Я руководитель команды разработки аналитических инструментов в VK. В этой статье расскажу о нашем опыте оптимизации Apache Superset под свои задачи.
Про BI в VK
Мы в VK применяем Data-driven подход, то есть принимаем решения на основе анализа данных и фактов. Аналитика позволяет нам отслеживать состояние процессов, оптимизировать продукты и сервисы, управлять рисками и безопасностью, улучшать пользовательский опыт и не только.
Мы развиваем BI в VK — и расскажем о нескольких трендах этого направления.
Тренд № 1. Единый BI
Исторически многие команды VK использовали разные BI-инструменты, исходя из собственных потребностей и экспертности. Но у этого есть обратная сторона — получается, что мы работаем с множеством разных технологий. В таком разнообразии проблематично ориентироваться и разбираться.
Поэтому в рамках стратегии внедрения сквозных технологий в VK мы решили определить единый для всех стек, за основу которого взяли Superset и Redash — все бизнес-юниты мигрировали свою аналитику на них.

Помимо этого, у нас исторически остался один инстанс DataLens, который решили оставить без изменений.
Так от множества систем осталось всего три. Но и на этом не остановились: сейчас пробуем объединить их в одну, которая будет работать под капотом нашего решения VK Horizon.

Тренд № 2. Распространение использования BI
Нам важно, чтобы сбор и аналитика данных приносили пользу и помогали находить точки роста продуктов и внутренних метрик. Поэтому мы отслеживаем использование BI внутри VK.
Так, исследование, проведённое в июле 2025 года, показало, что 55% целевых сотрудников регулярно (зачастую — еженедельно) используют наши BI-решения, и эта метрика постепенно растёт.
Причем они не только просматривают уже существующие дашборды, но и активно создают новые под свои задачи. Сейчас соотношение creator-viewer за месяц — 1 к 8, но при сохранении трендов оно может уменьшиться до 1 к 6.
Тренд № 3. Повышение стабильности дашбордов и демократизация разработки отчётов
Дашборд — инструмент для принятия решений. Нам важно, чтобы он работал стабильно и оперировал актуальными данными, которым можно доверять.
Но из-за ряда факторов это условие может не выполняться. Например:
-
Источник данных может быть перегружен, если не рассчитан на большое количество запросов

-
Запрос может стать слишком тяжёлым для источника. Например, нам нужно проанализировать значительную часть БД. Чем больше данных в базе, тем больше ресурсов уйдёт на эту операцию — и она может выполняться недопустимо долго

-
В Superset есть Jinja — шаблонный движок для Python, который нужен для динамического формирования SQL-запросов и построения визуализаций. Он позволяет встраивать выражения, условия и значения переменных в шаблоны SQL, что делает работу с большими наборами данных более гибкой. Но нюанс в том, что особые значения фильтра могут сломать SQL с Jinja

-
В отдельных случаях из-за низкой производительности обработки графики на дашбордах могут загружаться и отображаться с большой задержкой

Данные на дашбордах могут быть необъективными, также их может быть недостаточно, чтобы принять решение
Теоретически эти издержки можно исключить, определив ответственного за данные и дашборды. И чем меньше специалистов задействовано в пайплайне их подготовки, тем меньше потенциальных проблем и недопониманий.
Именно поэтому мы в VK позволяем упрощать разработку отчётов.
Раньше у нас в пайплайне было 5 этапов:
заказчик отдаёт ТЗ аналитику
аналитик обращается к дата-инженеру для построения витрин данных
дата-инженер формирует таблицу и отдаёт аналитику
аналитик составляет отчёт и отдаёт результаты заказчику

Это правильный путь. Но у него есть нюанс — time to market (TTM) отчёта в таком случае может составлять недели. Для нас это может быть критично, поскольку у нас динамическая среда — и при тестировании гипотез и подготовке новых релизов нам важно опираться на актуальные данные.
Чтобы оптимизировать процесс, мы допускаем исключение из этой цепочки дата-инженера: так он может сфокусироваться на основных бизнес-задачах и процессах. Формировать виртуальные таблицы начал аналитик. Согласований и ожиданий стало меньше, то есть ускорился time to market.

Можно упростить процесс еще сильнее. Например, если заказчик умеет писать SQL, то мы исключим из цепочки не только дата-инженера, но и аналитика. Но такой self-service возможен только в условиях высокого уровня Data Governance, к которому мы ещё идём.

В итоге мы пришли к тому, что семантический слой DWH (Data Warehouse) часто хранится в виртуальных SQL-датасетах BI-системы, то есть наш TTM больше зависит не от количества участников и ответственных, а от качества существующих дашбордов и оптимизации системы хранения датасетов — именно эту задачу мы и решали.
Модель данных в Superset
Чтобы пояснить суть наших действий, разберём модель данных в Superset.
Она довольно простая:
дашборды строятся по графикам
графики строятся на основе двух типов датасетов: физических и виртуальных
датасеты формируются на основе данных из источников

Соответственно, датасеты с контекстом чарта формируют SQL-запросы и отправляют их в источники для получения нужных данных.

Во многих BI-системах, в том числе Superset, есть встроенное кеширование. Благодаря этому получить данные, которые уже есть в кеше, будет значительно быстрее. Например, среднее время выполнения условного запроса к БД — 14 секунд, а среднее время загрузки из кеша — 0,8 секунды.

Есть нюанс: по нашим оценкам, обычно к БД направлены до 85% ежедневных запросов, и только в 15% случаев данные берутся из кеша. Во многом это происходит потому, что данные попадают в кеш, только если к ним кто-то уже обращался за последние сутки. Но у заказчиков могут быть разные контексты и потребности, и возможны ситуации, когда нужных данных может просто не оказаться в кеше. Поэтому мы решили прокачать работу кеша.
Первый этап: кеширование графиков по расписанию
Чтобы исключить случайное попадание данных в кеш, мы решили настроить кеширование графиков по расписанию, то есть делать это принудительно. Оптимально это делать на бэкенде, но так, чтобы не перегружать BI-систему и подключенные базы данных.
При этом мы настроили отправку Alerts&Reports в VK Teams. Благодаря этому аналитики или другие пользователи узнают, что в кеше появились актуальные данные, дашборд обновлён.

Но этого оказалось недостаточно. Настройки кеширования по расписанию фактически сводятся к тому, что нужно указать время, когда выполнять прогрев. Но идеальный сценарий для нас — сначала наполнить витрины данными и только после запускать их прогрев. Мы выстроили логику запуска прогрева данных при помощи корпоративного оркестратора OneFlow через API и сенсор ожидания полных данных в таблицах-источниках. В результате получили такой пайплайн:
get_tables: получаем источники дашборда
sensor: ожидаем сборку источников
warm_up: на основе статистики просмотров чартов прогреваем каждый график в топ-10 популярных значений фильтров

BI стал частью Data Platform, поскольку нам стало важно отслеживать триггеры и зависимости.
Уже на этом этапе мы получили буст по проценту попадания запросов в кеш и скорости загрузки. В кеш стали обращаться 26% запросов (вместо 15%), а скорость загрузки выросла на 12% (10,6 секунды против 12 секунд).
Метрика |
Было |
Стало |
Cache Miss |
85% |
74% |
Avg Cache Load |
0,8 с |
-//- |
Avg Query Load |
14 с |
-//- |
Avg Load |
12 c |
10,6 с |
Даже после этого оставались точки роста, которые можно было дополнительно оптимизировать. Для начала мы решили улучшить метрику Avg Cache Load, то есть среднее время загрузки данных из кеша.
Второй этап: ускоряем доступность данных из кеша
В кеше хранятся снапшоты данных, поэтому в теории ничто не мешает отдавать их без задержек. Но они всё же возникают, хоть и незначительные — те самые 0,8 с.
За это время система проверяет, можно ли конкретному пользователю отдавать запрашиваемый кеш. Она делает вывод на основе table-based access model (модели доступа на основе таблиц). Это можно было оптимизировать.
Основная сложность — нам нужна in-house проверка доступа пользователя к закешированным данным. Алгоритм проверки доступа должен быть максимально точным и работать быстро.
Изначально мы использовали sqlparse как библиотеку для извлечения таблиц из SQL. Но в рамках оптимизации решили заменить её самописным решением. Все основные отчёты у нас строятся на ClickHouse — и в первую очередь оптимизировать процессы нужно для неё. В результате разработали VK clickhouse-query-parser — библиотеку на Python. Она возвращает AST от SQL-запроса, на основе которого можно быстро извлечь используемые таблицы. VK clickhouse-query-parser использует бинарник, собранный из оригинального парсера ClickHouse. Поэтому наш парсер никогда не ошибается.
Мы сравнивали своё решение с sqlglot, чтобы протестировать его. Прогоны показали, что sqlglot иногда падает или неправильно находит используемые таблицы.

VK clickhouse-query-parser использует бинарный файл, собранный из C++ — это даёт стабильно высокую производительность.

С переходом на собственный парсер мы смогли выкрутить на максимум среднюю скорость загрузки данных из кеша: значение сократилось с 0,8 до 0,1 секунды.
Метрика |
Было |
Стало |
Cache Miss |
85% |
74% |
Avg Cache Load |
0,8 с |
0.1 с |
Avg Query Load |
14 с |
-//- |
Avg Load |
12 c |
10,6 с |
Осталось найти способ улучшить метрику Avg Query Load, то есть ускорить среднее время выполнения запросов. Важно было сделать это за счёт оптимизации системы хранения, а не переписывания запросов пользователей.
Третий этап: повышение производительности выполнения запросов
Несмотря на то что есть кеш, нам всё равно часто нужно обращаться к базе данных. У нас много дашбордов — 769 основных, а всего более 6 000 — и комбинаций контекстов для каждого, поэтому всё уместить в кеше Redis просто невозможно.
Нам нужно было решение, которое позволит прогревать много дашбордов, но при этом не перегрузит источник. И для которого не нужно хранить терабайты данных в Redis.
Мы проанализировали инструменты и выбрали VK ClickHouse API. Это наша библиотека-драйвер над ClickHouse, в которой есть упрощенная реализация MapReduce. В ней первый запрос выполняется на этапе map, а результат сохраняется во временную таблицу. Второй запрос, уже к полученной материализации, исполняется быстро благодаря предварительной обработке. Он сводит данные на этапе reduce.
К тому же у VK ClickHouse API есть много полезных фич:
контроль коннектов к кластеру — позволяет не перегрузить источник
сенсоры ожидания сборки таблиц-источников — защищают от использования неполных данных
высокая отказоустойчивость над ClickHouse — при сбое одной реплики он переключается на другую этого же шарда

Чтобы драйвер было удобно использовать, мы вынесли его в интерфейс Superset как опцию, которую в любой момент можно включить или выключить.
Покажем на примере, насколько эффективно работает VK ClickHouse API.
Допустим, у нас есть запрос, который выполняется 5 минут. Или не выполняется вообще и завершается по таймауту.

Но после включения CH API он выполняется меньше чем за минуту.

Материализация собирается и складывается в ClickHouse. Затем начинается стадия reduce: при создании визуализации (Chart) источником будут предварительно подготовленные данные — запрос идёт к ним. Запросы для построения графика (Chart SQL) идут напрямую к готовым экстрактам. В интерфейсе мы помечаем, что сборка идёт на основе экстракта.

Запрос визуализации также становится проще и короче. Мы используем FROM $table, чтобы указать, что применяем материализацию.

Если несколько графиков на дашборде используют один и тот же экстракт, они дедублицируются. Это позволяет снизить нагрузку и делать меньше повторных вычислений.

Подготовка экстрактов датасетов помогает нам сократить среднее время выполнения запросов с 14 до 8 секунд. Также увеличилась и средняя скорость загрузки дашбордов на 43% — она составила 5,9 секунды вместо 12.
Метрика |
Было |
Стало |
Cache Miss |
85% |
74% |
Avg Cache Load |
0,8 с |
0,1 с |
Avg Query Load |
14 с |
8 с |
Avg Load |
12 c |
5,9 с |
Схема работы экстрактов в VK Superset
Мы получили такой общий пайплайн:
Пользователь, открывая дашборд, часто попадает сразу в кеш: дефолтный контекст почти всегда есть в Redis Cache
При изменении внешнего фильтра используем высокодоступную материализацию в ClickHouse. Это позволяет отработать запрос за несколько секунд
Для динамических SQL-датасетов (с Jinja) нужно обращаться в ClickHouse-источник
Если нужны самые свежие данные — нужно настроить их репликацию в ClickHouse из распределённой системы хранения и обработки больших объёмов структурированных данных.
При этом каждый этап можно ставить на расписание в оркестраторе OneFlow, что позволяет отслеживать работу всей схемы.

Важно, что использование VK ClickHouse API в нашей реализации — опция. Пользователи по желанию могут выбирать между двумя вариантами пайплайна:
BI — cache — ClickHouse
BI — cache — VK CH API — ClickHouse
Краткое послесловие
Apache Superset — универсальный инструмент благодаря большому набору базовых функций и возможности гибкой кастомизации. Наш опыт показывает: чтобы повысить производительность решения, не обязательно изменять культуру разработки витрин данных и ограничивать построение дашбордов только аналитиками. Оптимизировать можно и работу самой системы. Благодаря интеграциям и разработанным технологиям мы добились двойного буста по скорости подготовки и отображения данных. Продолжаем оптимизировать реализацию SuperSet, переводя больше медленных сертифицированных дашбордов на схему с экстрактами.
Сталкивались ли вы с медленной загрузкой дашбордов при использовании open-source BI? Если да, как боролись с этим?