Data Apps Design
В этом блоге я публикую свои выводы и мнения на работу в Data: — Data Integration — Database engines — Data Modeling — Business Intelligence — Semantic Layer — DataOps and DevOps — Orchestrating jobs & DAGs — Business Impact and Value
Ko'proq ko'rsatish- Kanalning o'sishi
- Post qamrovi
- ER - jalb qilish nisbati
Ma'lumot yuklanmoqda...
Ma'lumot yuklanmoqda...
staging: +docs: node_color: "#219EBC"🔴Скрыть нерелевантные модели из документации
models: <resource-path>: +docs: show: true | false🟤Блоки
{{ doc() }}
: Переиспользование блоков документации
В целом, большие блоки документации стоит вынести в отдельные markdown-файлы. Возможно, с картинками и схеми.
Также имеет смысл один раз описать атрибут (колонку), который присутствует в 1+ моделях, и впоследствие ссылаться на его описание:
models: - name: events description: '{{ doc("table_events") }}'🩷Custom overview page - главная страница сайта с документацией Рекомендую грамотно использовать title page и разместить на нем самую важную информацию: — Используемые инструменты и сервисы — Архитектурная схема — Описание источников данных — Ссылки на JIRA (task trackers), Wiki pages, Operational systems, Contacts (@), etc.
{% docs __overview__ %} ## OVERVIEW ## INFRASTRUCTURE SCHEMA ## TOOLS USED ## DATA SOURCES ## USEFUL LINKS {% enddocs %}🟢Публикация вебсайта Т.к. сайт статический, его достаточно разместить в Object Storage с поддержкой Static website hosting: — Host on Amazon S3 (optionally with IP access restrictions) — Publish with Netlify — Use your own web server like Apache/Nginx 🟡Актуализация вебсайта с документацией - всегда Up to Date Чтобы вебсайт всегда отражал актуальное состояние, необходимо после каждого изменения в код (Merge Request), генерировать и загружать новую версию. Делать это можно с помощью Github Actions или аналогов, автоматизируя действия: —
dbt docs generate
— aws s3 sync ./target s3://my-website-bucket/
🌐 @data_apps | Навигация по каналу- ЕСТЬ NRT / STREAMING; ЕСТЬ необходимость или бизнес-обоснование (есть NRT-задача и она решается)
- ЕСТЬ NRT / STREAMING; НЕТ необходимости (просто хочется минимальное отставание)
- НЕТ NRT / STREAMING; и ЕСТЬ необходимость (есть NRT-задача и она пока не решена, но хочется)
- НЕТ NRT / STREAMING; и НЕТ необходимости (устраивает подход BATCH)
df -hЧто делать? Как перенести Docker Volumes и избежать ошибки Disk full? 🔺 Действия — Добавить новый Filesystem, на котором будет достаточно места — Остановить контейнеры — Отключить Docker services — Unmount docker overlay filesystems — Перенести данные в новый раздел — Внести изменения в конфигурационный файл Docker daemon.json — Включить Docker services — Запустить контейнеры 🟡 Скрипт
# Stop Docker containers
docker compose stop
# Stop Docker services
systemctl stop docker
systemctl stop docker.socket
# Unmount docker filesystems
umount /var/lib/docker/overlay2/*/*
# Move data
mv /var/lib/docker/ /mnt/${DESTINATION}/
# Edit Docker service configuration file:
nano /etc/docker/daemon.json
# Add or modify the data-root configuration option to point to the new directory:
{
"data-root": "/mnt/path/docker"
}
# Save and close the file.
# Start the Docker service:
systemctl start docker
systemctl start docker.socket
# Start Docker containers
docker compose start
Также этот скрипт на Github Gist: https://gist.github.com/kzzzr/fef4c9c88f301c282275e6d451e080f5
Это сработало для меня, и должно сработать для вас.
В частности, это позволило мне расширить дисковое пространство на VM, и позволить Docker писать в новую Filesystem БЕЗ повторного запуска full sync истории по 100+ коллекциям MongoDB (Debezium Connector + Kafka topics).
🌐 @data_apps | Навигация по каналуDocker: move persistent volumes (mounts) into another filesysytem with data losses - docker.md
ts_ms
= metadata timestamp
— op
= c (create), u (update), d (delete), r (snapshot)
🔴 Message transformations: Topic route, New Document State Extraction
— Topic route: Мессаджи направляю сразу в топики с целевыми названиями таблиц в Snowflake.
— New Document State Extraction: этат трансформация позволяет перейти от сложного и детального формата события Debezium (schema, before, after) к упрощенному виду (только after), который мне и нужен в Snowflake.
🟤 Debug events
Развернул devcontainer (docker-compose based), установил kcat + jq.
Использую kcat для просмотра топиков, key-value значений, оффсетов.
jq использую для форматирования ответов от REST API (Kafka Connect).
Очень удобно проконтролировать изменения, которые вношу пунктом ранее.
🟡В следующем посте:
— Externalizing secrets
— Create a sink connector (Snowflake)
— Set up monitoring (Prometheus + Grafana)
— Use AVRO data format (io.confluent.connect.avro.AvroConverter
)
— Configure topics (compact + delete, etc.)
— Configure incrmental snapshots loads via Debezium signals
— Ensure PII data masking (message transformations, connector configuration)
— Add HTTP bridge / REST proxy
🔻 Могли бы покритиковать / поделиться опытом / посоветовать что-либо?
🌐 @data_apps | Навигация по каналу {#- prepare expression to limit rows depending on target.name and flags provided -#}
{%- if target.name in ['prod'] and history_depth_days > 0 -%}
{%- set watermark = 'DATEADD(days, ' ~ -1 * history_depth_days ~ ', CURRENT_TIMESTAMP::DATE)' -%}
{%- set history_depth_expression = timestamp_column ~ ' >= ' ~ watermark -%}
{%- elif target.name not in ['prod'] and limit_data_for_dev == true -%}
{%- set watermark = 'DATEADD(days, ' ~ -1 * var('data_tests_depth_days') ~ ', CURRENT_TIMESTAMP::DATE)' -%}
{%- set history_depth_expression = timestamp_column ~ ' >= ' ~ watermark -%}
{%- else -%}
{%- set history_depth_expression = '1 = 1' -%}
{%- endif -%}
{#- prepare final filter expression -#}
where 1 = 1
and {{ deleted_rows_expression }}
and {{ history_depth_expression }}
🩷 Уровень серьезности (Severity) теста: ERROR для PROD, WARN для DEV:
- name: timezone tests: - dbt_utils.not_null_proportion: at_least: 0.95 severity: "{{ 'error' if target.name in ('prod') else 'warn' }}"🩷 Используемый COMPUTE в зависимости от среды:
{{
config(
materialized='table',
snowflake_warehouse='WH_LARGE' if target.name == 'prod' else target.warehouse
)
}}
🩷 Запись артефактов dbt run в метаданные (только для PROD):
on-run-end: - "{% if target.name == 'prod' %}{{ dbt_artifacts.upload_results(results) }}{% endif %}"✅ Какие преимущества — Все пользуются одними и теми же исходными наборами данных (data sources) - исключены расхождения и несогласованность — Zero effort - не нужно создавать среды как отдельные инстансы, разворачивать ПО, копировать датасеты и следить за актуальностью — Один проект = один репозиторий с кодом ✔ — Разница поведения и конфигураций для разных сред легко поддерживается с помощью шаблонизации Jinja SQL — Это экономически выгодно и целесообразно. Используя Snowflake вообще perfect, т.к. у вас decoupled storage & compute, при этом compute unlimited — Это быстро и безболезненно с точки зрения поставки кода и Time2Market ❤ Расскажите, как эти процессы реализуете вы? В чем недостатки и преимущества подхода? 🌐 @data_apps | Навигация по каналу
git clone --depth=1 https://github.com/apache/superset.git
export TAG=3.1.1
docker compose -f docker-compose-image-tag.yml up
Есть варианты с Kubernetes, PyPI
🟤 Доступна локализация Superset на русский язык
Выполняется как добавление русского языка в список доступных:
LANGUAGES = {
"ru": {"flag": "ru", "name": "Русский"},
"en": {"flag": "us", "name": "English"}
}
🟡Подключение к источнику данных Clickhouse
Из коробки в Superset нет возможности подключиться к Clickhouse.
В моем случае, я выполнил скрипт установки в одном из контейнеров:
pip install clickhouse-connect
Возможно собирать готовые образы с предустановленными драйверами и пользовательскими конфигурациями.
🔵 Использование семантического слоя Cube в качестве Database Connection
Всё работает замечательно.
Cube показывает Postgres-подобный SQL API, который можно использовать в Superset из коробки.
🔸 Однако, в случае, если вы хотите применять custom formatting для ряда метрик (.2%
- доля в процентах до двух знаков после запятой), то вам придется задать METRICS (формула + название) и в Superset, т.е. по сути выполнить задать метрику дважды, что не очень хорошо.
🟫 Также новые метрики доступны к использованию только после явного Dataset metadata refresh. Т.е. даже в случае Continuous Deployment придется пройти и нажать все кнопочки явным образом.
🔴 Графики на Apache ECharts
Почему Apache ECharts? Коротко:
— large library of visualization types
— high performance, ideally supporting canvas rendering
— powerful declarative API for customizing and theming charts
— internationalization support
— an active and growing community
❤️ Уже заценил Mixed chart, где можно совместить несколько метрик различных типов (bar + line) с общей осью (X = Time).
🟢 Кастомизации графиков
Итак, порой у пользователей дашбордов возникают странные и на первый взгляд неосуществимые требования 🟢:
— Применение особенного форматирования - stacked bar chart values alignment (center)
— Добавление строк, колонок в визуализацию (пустые строки-разделители Excel-like) - попробуем Custom CSS
— Новые (недоступные из коробки) визуализации - обратимся к библиотеке Apache ECharts
— Расширенное редактирование имеющихся графиков
Мне еще многое предстоит выяcнить в этих моментах, но учитывая наличие материалов, думаю, что это будет осуществимо.
🩷 В Tg есть русскоязычное community @superset_ru
— Многие вопросы находятся в поиске по ключевым словам
— Ранее не обсуждавшийся вопрос можно сформулировать и задать коллективному разуму
Не всё получается сделать сразу, быстро и просто. Но пока впечатления положительные.
👤 Поделитесь, какие ваши? Сталкивались с тем, что не получалось решить? Раздражало в Superset?
🌐 @data_apps | Навигация по каналуНа кейсе создания витрины корпоративных метрик рассмотрим: — Элементы functional programming c dbt macros — Интерактивный UX с dbt Power User + CLI — Импорт и переиспользование кода с dbt packages — Универсальный код и окружения с dbt adapters Бизнес-задача: Дашборд для Weekly Business Review (WBR) Требования к дашборду: — Nesting: от верхнеуровневых метрик к детальным — Набор измерений для Slice and Dice — Формат графика для метрики — Линии для Year over Year (abs + rel %) — Визуализация целевых значений (targets) — Решение «Hardcore Cube» 🗿 — Решение «Direct Runtime» 🦅 — Aggregate awareness (Looker) как оптимизация производительности — Как отразилась смена СУБД с Amazon Redshift на Snowflake на решении? Как всё это использовать у себя? — Находите повторяющиеся паттерны и переиспользуйте код (DRY) — Пишите универсальный код с dbt — Не изобретайте велосипед - используйте packages — Ищите баланс между материализацией и runtime queries — Чем меньше кода, тем лучше Data Apps Design:
https://t.me/data_appsУчиться со мной:
https://forms.gle/uwETpSRA6ux7Gr1t7Таймкоды: 00:40 — Артемий Козырь - обо мне 01:10 — Weekly Business Review 03:03 — Требования к дашборду WBR 08:45 — Решение #1 «Hardcore Cube» 🗿 13:25 — Решение #2 «Direct Runtime» 🦅 16:02 — Дашборд работает дико медленно и раздражает всех! 18:23 — Давайте ускорим это 22:03 — Решение «Godlike modeling» 👑 28:44 — Я поменял СУБД Amazon Redshift на Snowflake 29:37 — Выводы и итоги 33:15 — Вопрос: Чем решение отличается от стека Microsoft SSAS 34:50 — Вопрос: Почему бы не использовать HyperLogLog (HLL) Approximation для ускорения ответов 37:55 — Вопрос: Как подсчитать и сравнить стоимость решений, оптимизация затрат 39:52 — Вопрос: Кубы и dbt модель собираются incremental (инкрементально) или full refresh? 40:50 — Вопрос: Почему используется Looker в качестве BI? В чем плюсы? Есть ли альтернативы? 42:25 — Вопрос: Как построить инкрементальные расчеты и наполнение витрин с dbt? 43:44 — Вопрос: Почему со временем без рефакторинга кода производительность становится хуже? 46:25 — Вопрос: Как осуществляется оркестрация запусков? Использование dbtCloud
Joriy rejangiz faqat 5 ta kanal uchun analitika imkoniyatini beradi. Ko'proq olish uchun, iltimos, boshqa reja tanlang.