- PVSM.RU - https://www.pvsm.ru -
В начале немного контекста. Я — аналитик данных в команде BIGDATAHOUSE, и на всех проектах трансформацию данных реализую через dbt — де‑факто стандарт, в качестве BI в основном использую Superset. Бизнес‑логика в таком стеке оказывается разбита по двум местам: одна её часть оседает в dbt, другая описывается в BI. Со временем эти две части неизбежно расходятся, и отследить такие расхождения становится всё сложнее. Из профессионального интереса изучая альтернативные BI‑платформы, я наткнулся на Lightdash. Он обещает закрыть эту и ряд других проблем.
Теперь представьте ситуацию (возможно некоторым и представлять не нужно, достаточно вспомнить рабочие будни): на созвоне кто‑то задаёт вопрос «а какая у нас выручка за квартал?», и в этот момент одновременно озвучивают три разных цифры. Одна из дашборда в Superset, вторая из выгрузки CSV файла, а третья из SQL запроса к базе данных. И дальше команда обсуждает не бизнес задачу, а то, какая цифра является корректной. Но проблема может быть даже не в ошибке расчётов, а в том, что каждый держит в голове своё определение выручки.
Эту неоднозначность закрывают инструменты семантического слоя: метрика описывается один раз в коде (об этом чуть позже), и везде — от ad‑hoc запросов до дашбордов — используется одно и то же определение.
Одним из таких инструментов и является Lightdash — BI‑платформа с открытым исходным кодом, предоставляющая возможность нетехническим пользователям самостоятельно исследовать показатели, строить визуализации и дашборды (ведь метрики и измерения описывают аналитики и дата‑инженеры, а дальше в BI работают уже все желающие, например, менеджеры или руководители).
Главная особенность Lightdash как раз в том, что он изначально строится вокруг dbt и семантического слоя. Вместо того чтобы реализовывать ещё один слой моделирования в BI‑инструменте, Lightdash берёт dbt‑модели и YAML‑определения метрик как единственный источник истины. Метрики и модели версионируются, любые изменения проходят ревью, их можно легко откатить, покрыть тестами. Благодаря этому Lightdash наследует все ключевые преимущества dbt и переносит их в пласт BI.
Таким образом, платформа ощущается как естественное продолжение современного дата‑стэка, а не обособленная система, где данные нужно проектировать заново.
Начну не с теории, а с демонстрации простого сценария: допустим, перед вами стоит задача узнать, сколько было клиентов и какой объём денежных средств они принесли за определённый период времени.
При иных обстоятельствах приходится обращаться к аналитикам и ожидать их ответа в виде графика или выгрузки в другом формате. В Lightdash это происходит следующим образом: вы открываете список таблиц (на самом деле это dbt‑модели с описанием метаданных в формате YAML), выбираете необходимую для исследования и попадаете в раздел «Explore» — слева панель с готовыми измерениями и метриками, справа — пустой холст. Не нужно писать ни строчки SQL‑кода, визуализация строится по принципу drag‑and‑drop, далее настраиваете фильтры, внешний вид графика (кастомизация, кстати, в Lightdash держит достойный уровень и заслуживает отдельного обзора разнообразия визуализаций в целом и их «продвинутых» настроек) и получаете ответ на бизнес‑вопрос, а если запросов несколько — чарты собираются в дашборд.
models:
- name: customers
config:
meta:
primary_key: customer_id
joins:
- join: orders
sql_on: ${customers.customer_id} = ${orders.customer_id}
relationship: one-to-many
- join: payments
sql_on: ${orders.order_id} = ${payments.order_id}
relationship: one-to-many
columns:
- name: customer_id
description: This is a unique identifier for a customer
tests:
- unique
- not_null
config:
meta:
dimension:
type: number
metrics:
unique_customer_count:
tags: ["period_metric"]
type: count_distinct
label: Unique customer count
description: Total number of customers
spotlight:
categories: ["core", "revenue_growth"]
total_order_amount_deduped:
type: sum_distinct
sql: ${orders.amount}
distinct_keys: [orders.order_id]
format: usd
round: 2
- name: created
description: Timestamp (UTC) when customer was created
config:
meta:
dimension:
type: timestamp
metrics:
date_of_first_created_customer:
type: min
date_of_most_recent_created_customer:
type: max
Буквально пара слов про сам dbt — это инструмент трансформации данных в хранилище: вы пишете SQL‑запросы (модели), а dbt сам понимает порядок их выполнения, материализует результаты, тестирует и генерирует документацию. С SQL‑моделями сосуществуют YAML‑файлы с метаданными.
Прежде чем разбирать, почему график собрался за пару кликов, стоит понять одну неочевидную вещь про файл выше — это файл из dbt‑проекта, но не весь он «про dbt».
dbt из этого YAML знает не все инструкции: models, name, description, columns, tests (unique, not_null), config — это стандартные свойства модели [2], которые dbt читает, валидирует и использует для генерации документации и тестов. А вот всё, что лежит внутри конфига [3]meta — dimension, metrics, joins — dbt не интерпретирует вообще. Для него meta — это произвольный словарь, который он пробрасывает дальше, не заглядывая внутрь.
Именно здесь и появляется Lightdash. Он читает тот же файл, но смотрит в meta и достаёт оттуда свою семантику [4]: метрики, измерения и связи, YAML остаётся полностью валидным dbt‑файлом, проект собирается и тестируется как обычно, а BI‑логика живёт рядом, ничего не нарушая.
Обратите внимание на блок [5]joins в конфиге — там ответ на вопрос «почему простой drag‑and‑drop корректно обрабатывает композитные метрики». Заметьте две инструкции, обе снимают с конечного пользователя работу, которую иначе пришлось бы реализовывать на SQL:
sql_on — условие соединения (ON из JOIN). Заполняется один раз и в дальнейшем любые чарты, где потребуется соединение таблицы customers с orders или payments будут объединены именно по этому правилу;
relationships определяет мощность связи, например, связь customers → orders обозначена как one‑to‑many, то есть одному клиенту соответствует много заказов.
И тут стоит заметить, что метрика total_order_amount_deduped с distinct_keys нужна именно потому, что связь customers → orders → payments множит строки, но теперь Lightdash об этом осведомлён и считает сумму корректно.
Коротко о блоке [6]metrics:
unique_customer_count — count_distinct по customer_id = кол‑ву уникальных клиентов;
total_order_amount_deduped — sum_distinct с distinct_keys = дедуплицированной сумме заказов.
Т.е. левая панель в UI содержит не сырые колонки, а готовые агрегации с предопределёнными типами [7]. Вы выбираете «что» посчитать, а «как» — определено в YAML файлах.
Измерения [8] — это то, по каким атрибутам вы группируете. Описали колонку в YAML (в примере выше — created — дата создания пользователя), и она доступна в BI, с соответствующим типом данных, от которого зависят доступные фильтры.
В Lightdash любой агрегат можно проверить, к примеру, чтобы понять, откуда на графике резкий выброс значений. Для этого достаточно кликнуть по элементу визуализации (столбцу, точке, ячейке таблицы) и выбрать «View underlying data» — на скриншотах ниже это показано на конкретном примере: круговая диаграмма с распределением суммы заказов по странам, кликаем по US. Видно меню и открывшуюся следом таблицу сырых строк, собранную с учётом тех же фильтров и группировок, что и на графике.


Основные метрики живут в YAML и они могут быть сколь угодно сложными. Но заводить новый показатель в коде ради одной цифры в отчёте или проверки гипотезы может быть избыточно.
Для таких разовых запросов и существуют вычисляемые поля, которые создаются прямо в чарте поверх уже выбранных метрик: доли, накопительные итоги, ранги, изменения к прошлому периоду и так далее.
Наглядный пример — средний чек в разрезе стран. В чарте по country_orders уже выбраны total_order_amount и order_count, и этого достаточно: добавляете table calculation @{total_order_amount} / @{order_count} — и рядом с суммой и количеством заказов появляется новая колонка со средним чеком по каждой стране.


Lightdash хранит историю версий каждого чарта: можно посмотреть, что и когда менялось, и откатиться к любой предыдущей версии — отличная страховка для командной работы.

Доступ в Lightdash можно ограничивать не только на уровне проекта, но и на уровне отдельных полей и метрик. В YAML для этого прописывается условие доступа — блок required_attributes. Например, так чувствительное поле скрывается от всех, кроме администраторов:
columns:
- name: age
meta:
dimension:
required_attributes:
is_admin: "true"
Пользователь без указанного значения (is_admin: "true") это поле просто не увидит — вместе со всеми метриками, которые от него зависят. Если условий несколько, required_attributes работает по логике 'И', а конструкция any_attributes — по логике 'ИЛИ'.
Сами пользовательские атрибуты (user attributes [9]) при этом создаёт админ через интерфейс и назначает значения конкретным пользователям или группам. В YAML вы лишь ссылаетесь на нужное условие — кому и какое значение присвоено, решается в UI.
А если ограничивать нужно не колонки, а строки, есть конструкция sql_filter, которая добавляет условие прямо в WHERE запроса к хранилищу.
Получается row/column‑level security, описанная в коде, рядом с самими данными.
Lightdash умеет поднимать превью проекты и валидировать контент через CI/CD, и для команды разработки это удобный паттерн, заметно отличающий Lightdash от других BI‑инструментов.
Превью проект [10] — это временная копия продакшн проекта: чарты и дашборды копируются из продакшна и можно безопасно экспериментировать с метриками, измерениями и контентом. Настроив GitHub Actions, вы получаете такой проект автоматически на каждый пулл‑реквест, при каждом новом коммите превью обновляется, а после мержа или закрытия PR удаляется.
Теперь про валидацию контента: команда [11]lightdash validate проверяет, не нарушают ли внесённые изменения существующие чарты и дашборды. В CI процессе эту команду используют как триггер перед принятием изменений: при обнаружении ошибок правки не попадут в основную ветку, пока проверка не завершится успешно. Результат валидации доступен и в интерфейсе: в настройках проекта есть вкладка «Validator» со списком повреждённых чартов и дашбордов и причинами ошибок. Стоит учитывать ограничение: валидатор проверяет ссылки и определения метрик и измерений, но не исполняемый SQL, поэтому ошибку в синтаксисе запроса он не обнаружит.
Помимо этого, Lightdash делает контент управляемым через код наравне с моделями: чарты и дашборды выгружаются в YAML, правятся и загружаются обратно через командную строку — в результате визуализации версионируются и проходят ревью так же, как dbt‑модели. dbt write‑back [12] работает в обратную сторону: новое измерение создаётся прямо в интерфейсе Lightdash, а его YAML‑описание отправляется запросом на слияние в репозиторий dbt.
В этой части я постарался показать Lightdash с двух сторон. Сначала — как идею: бизнес‑логика живёт в dbt, а BI лишь читает её из YAML, не заводя собственного слоя моделирования. Затем — как инструмент: разобрал устройство YAML‑файла, drill‑down до сырых строк, вычисляемые поля, версионирование чартов, управление доступом через пользовательские атрибуты, а также превью‑проекты и валидацию контента.
Уместить всё в одну статью не получилось бы: только библиотека визуализаций и их настройки тянут на отдельный разбор. Поэтому материал выходит порционно.
Во второй части я планирую:
собрать полноценный дашборд и разобрать его фильтры и оформление;
пройтись по библиотеке визуализаций и их кастомизации, включая кастомные чарты на Vega‑Lite;
объективно разобрать недостатки;
сравнить облачную версию и self‑hosted;
подвести итог: кому инструмент подойдёт, а кому разумнее остаться на привычном стеке.
А пока можно самостоятельно пощупать Lightdash: есть публичное демо [13], где без установки и собственного dbt‑проекта доступны примеры визуализаций и запросов. Полноценного опыта «метрик как кода» оно не даст, но для первого знакомства этого достаточно.
Автор: thirstforgl
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/vizualizatsiya-danny-h/456172
Ссылки в тексте:
[1] streamable.com: https://streamable.com/4690l4
[2] свойства модели: https://docs.getdbt.com/reference/model-properties
[3] конфига : https://docs.getdbt.com/reference/resource-configs/meta?version=2.0&name=Fusion
[4] семантику: https://docs.lightdash.com/guides/lightdash-semantic-layer
[5] блок : https://docs.lightdash.com/references/joins
[6] блоке : https://docs.lightdash.com/references/metrics
[7] типами: https://docs.lightdash.com/references/metrics?spm=a2ty_o01.29997173.0.0.169d55fbkfR5ly
[8] Измерения: https://docs.lightdash.com/references/dimensions?spm=a2ty_o01.29997173.0.0.169d55fbkfR5ly
[9] user attributes: https://docs.lightdash.com/references/workspace/user-attributes
[10] Превью проект: https://docs.lightdash.com/guides/developer/preview-projects
[11] команда : https://docs.lightdash.com/guides/cli/how-to-use-lightdash-validate
[12] dbt write‑back: https://docs.lightdash.com/guides/developer/dbt-write-back
[13] публичное демо: https://demo.lightdash.com
[14] Источник: https://habr.com/ru/articles/1067570/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1067570
Нажмите здесь для печати.