{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Yuriy Gavrilov: posts tagged Data Visualization",
    "_rss_description": "Welcome to my personal place for love, peace and happiness 🤖 Yuiry Gavrilov",
    "_rss_language": "en",
    "_itunes_email": "yvgavrilov@gmail.com",
    "_itunes_categories_xml": "",
    "_itunes_image": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic-square@2x.jpg?1643451008",
    "_itunes_explicit": "no",
    "home_page_url": "https:\/\/gavrilov.info\/tags\/data-visualization\/",
    "feed_url": "https:\/\/gavrilov.info\/tags\/data-visualization\/json\/",
    "icon": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic@2x.jpg?1643451008",
    "authors": [
        {
            "name": "Yuriy Gavrilov - B[u]g - for charity.gavrilov.eth",
            "url": "https:\/\/gavrilov.info\/",
            "avatar": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic@2x.jpg?1643451008"
        }
    ],
    "items": [
        {
            "id": "279",
            "url": "https:\/\/gavrilov.info\/all\/iskusstvo-skorosti-rukovodstvo-po-optimizacii-dlya-analitiki-v-d\/",
            "title": "Искусство скорости: Руководство по оптимизации для аналитики в Data Lakehouse с DuckDB",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-09-09-v-01.35.35.png\" width=\"1174\" height=\"108\" alt=\"\" \/>\n<\/div>\n<p>DuckDB завоевал огромную популярность как “SQLite для аналитики”. Это невероятно быстрый, встраиваемый, колоночный движок, который не требует отдельного сервера. Однако его мощь по-настоящему раскрывается, когда он получает доступ к данным эффективно. Просто натравить DuckDB на петабайтный дата-лейк без подготовки — это рецепт для медленных запросов и высоких затрат.<\/p>\n<p>Как же построить мост между огромным хранилищем данных и молниеносной интерактивной аналитикой, которую обещает DuckDB?<\/p>\n<div class=\"e2-text-video\">\n<video src=\"https:\/\/gavrilov.info\/video\/-5436782684090959843.mp4#t=0.001\" width=\"640\" height=\"480\" controls alt=\"\" \/>\n\n<\/div>\n<p>В этой статье рассмотрим три фундаментальных архитектурных подхода к организации доступа к данным для DuckDB. Но прежде чем мы погрузимся в то, как *читать* данные, давайте поговорим о том, как их *готовить*.<\/p>\n<h4>Большая картина: Подготовка данных с помощью Trino<\/h4>\n<p>Данные в вашем Lakehouse не появляются из ниоткуда. Они поступают из операционных баз данных, потоков событий (Kafka), логов и десятков других источников. Прежде чем DuckDB сможет их эффективно запросить, эти данные нужно собрать, очистить, трансформировать и, что самое важное, организовать в надежный и производительный формат.<\/p>\n<p>Здесь на сцену выходит <b>Trino<\/b> (ранее известный как PrestoSQL).<\/p>\n<p><b>Что такое Trino?<\/b> Это мощный распределенный SQL-движок, созданный для выполнения запросов к гетерогенным источникам данных. Его суперсила — способность “на лету” объединять данные из PostgreSQL, Kafka, Hive, MySQL и многих других систем.<\/p>\n<p><b>Роль Trino в Lakehouse:<\/b> В современной архитектуре Trino часто выступает в роли “фабрики данных”. Он выполняет тяжелую работу по <b>ETL\/ELT<\/b> (Extract, Transform, Load), подготавливая данные для аналитических инструментов вроде DuckDB.<\/p>\n<p><b>Типичный сценарий использования:<\/b><\/p>\n<ol start=\"1\">\n<li><b>Источники:<\/b> У вас есть события о прослушивании треков в Kafka, а информация о пользователях — в базе данных PostgreSQL.<\/li>\n<li><b>Задача:<\/b> Создать единую, денормализованную таблицу Iceberg для аналитики.<\/li>\n<li><b>Решение с Trino:<\/b> Вы настраиваете в Trino коннекторы к Kafka и PostgreSQL. Затем вы запускаете периодический SQL-запрос, который читает данные из обоих источников, объединяет их и записывает результат в новую или существующую таблицу Iceberg.<\/li>\n<\/ol>\n<pre class=\"e2-text-code\"><code class=\"\">-- Этот запрос выполняется в Trino, а не в DuckDB!\n    INSERT INTO iceberg_catalog.analytics.daily_user_activity\n    SELECT\n        u.user_id,\n        u.country,\n        e.event_timestamp,\n        e.track_id,\n        e.duration_ms\n    FROM\n        postgres_catalog.public.users u\n    JOIN\n        kafka_catalog.raw_data.listen_events e ON u.user_id = e.user_id\n    WHERE\n        e.event_date = CURRENT_DATE;<\/code><\/pre><p>Как отмечается в одном из руководств, именно такой `INSERT INTO ... SELECT ...` является типичным способом перемещения данных в Iceberg с помощью Trino.<\/p>\n<p><b>Итог:<\/b> Trino работает “глубоко в машинном отделении” вашего Lakehouse. Он берет на себя тяжелые, распределенные задачи по преобразованию данных, а DuckDB получает на вход уже чистые, структурированные и оптимизированные для чтения таблицы Iceberg.<\/p>\n<p>Теперь, когда данные готовы, давайте рассмотрим, как их лучше всего потреблять.<\/p>\n<h4>Подход 1: Табличные форматы (Iceberg) — Читайте только то, что нужно<\/h4>\n<p>Это самый продвинутый и рекомендуемый подход для серьезной аналитики, особенно в serverless-архитектуре.<\/p>\n<ul>\n<li><b>Как это работает:<\/b> Вместо того чтобы работать с “россыпью” файлов Parquet, вы работаете с логической таблицей, управляемой Apache Iceberg. Расширение `iceberg` в DuckDB использует метаданные Iceberg для интеллектуального отсечения ненужных файлов (partition pruning) и блоков данных (predicate pushdown), читая с диска минимально необходимый объем информации.<\/li>\n<li><b>Архитектура:<\/b> `Данные на S3 -> Trino (ETL) -> Таблица Iceberg -> DuckDB (Аналитика)`<\/li>\n<\/ul>\n<h5>Назначение и сценарии использования:<\/h5>\n<ul>\n<li><b>Serverless-аналитика:<\/b> Основной кейс. AWS Lambda или Google Cloud Function, оснащенная DuckDB, выполняет SQL-запрос к озеру данных. Благодаря Iceberg, функция читает всего несколько мегабайт вместо гигабайт, что делает ее выполнение быстрым (<1 сек) и дешевым.<\/li>\n<li><b>Локальная разработка и BI:<\/b> Аналитик данных или инженер открывает Jupyter Notebook на своем ноутбуке. С помощью DuckDB он подключается напрямую к производственному Lakehouse и выполняет исследовательский анализ, не создавая копий данных и не перегружая кластеры.<\/li>\n<li><b>Встраиваемая аналитика:<\/b> Backend-сервис на Python или Node.js, которому нужно быстро отвечать на аналитические вопросы (например, “показать статистику пользователя за последний месяц”). Он использует DuckDB для прямого запроса к Lakehouse без обращения к промежуточной базе данных.<\/li>\n<\/ul>\n<h4>Подход 2: RPC-стриминг (Apache Arrow Flight) — Прямой канал к данным<\/h4>\n<p>Иногда вам не нужна вся мощь Iceberg, а нужно просто эффективно выполнить запрос на удаленном экземпляре DuckDB и получить результат.<\/p>\n<ul>\n<li><b>Как это работает:<\/b> Вы запускаете сервер, который инкапсулирует DuckDB. Клиент и сервер общаются по протоколу Arrow Flight — высокопроизводительному фреймворку для стриминга колоночных данных в формате Apache Arrow без затрат на сериализацию.<\/li>\n<li><b>Архитектура:<\/b> `Клиент -> Arrow Flight RPC -> Сервер с DuckDB -> Данные (любой источник)`<\/li>\n<\/ul>\n<h5>Назначение и сценарии использования:<\/h5>\n<ul>\n<li><b>Интерактивные дашборды:<\/b> Веб-интерфейс (React, Vue) должен строить графики в реальном времени. Он отправляет SQL-запросы на Flight-сервер и получает данные для отрисовки практически мгновенно, без “тяжести” HTTP\/JSON.<\/li>\n<li><b>API-шлюз для данных:<\/b> Централизация доступа к данным для множества внутренних микросервисов. Вместо того чтобы каждый сервис имел свои креды и логику подключения к БД, они обращаются к единому, стабильному Flight API.<\/li>\n<li><b>Кросс-языковое взаимодействие:<\/b> Сервис на Java должен получить результаты вычислений из BI-системы, построенной на Python и DuckDB. Arrow Flight обеспечивает эффективный и стандартизированный мост между ними.<\/li>\n<\/ul>\n<h4>Подход 3: “API поверх данных” (ROAPI & DataFusion) — Декларативная альтернатива<\/h4>\n<p>Что, если вам не нужна вся гибкость SQL, а нужен стандартный REST или GraphQL API поверх ваших данных без строчки кода? Здесь на сцену выходит <b>ROAPI<\/b>.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-212.png\" width=\"1612\" height=\"1435\" alt=\"\" \/>\n<\/div>\n<ul>\n<li><b>Как это работает:<\/b> ROAPI — это инструмент, который автоматически создает API, читая конфигурационный YAML-файл, где вы описываете ваши данные (Parquet, CSV и т.д.). Под капотом он использует Apache Arrow DataFusion, движок запросов, написанный на Rust, являющийся идейным братом DuckDB.<\/li>\n<li><b>Архитектура:<\/b> `Клиент (HTTP\/GraphQL) -> ROAPI Server -> Данные (файлы)`<\/li>\n<\/ul>\n<h5>Назначение и сценарии использования:<\/h5>\n<ul>\n<li><b>Быстрое прототипирование:<\/b> Вам нужно за 5 минут предоставить команде фронтенда API для нового набора данных. Вы пишете 10 строк в YAML, запускаете ROAPI — и API готов.<\/li>\n<li><b>Простые микросервисы данных:<\/b> Сервис, единственная задача которого — раздавать данные из файла с поддержкой фильтрации и пагинации. ROAPI делает это из коробки, избавляя вас от написания рутинного кода на FastAPI или Express.js.<\/li>\n<li><b>Дата-фиды для внешних систем:<\/b> Предоставление стандартизированного API для партнерской системы, которая умеет работать с REST, но не умеет читать Parquet.<\/li>\n<\/ul>\n<h4>и еще немного про DuckDB<\/h4>\n<h5>1. Читайте меньше данных (Золотое правило)<\/h5>\n<ul>\n<li><b>Используйте Iceberg:<\/b> Это лучший способ.<\/li>\n<li><b>Проекция колонок (`SELECT col1, col2...`):<\/b> <b>Никогда не используйте `SELECT *`<\/b>.<\/li>\n<li><b>Проталкивание предикатов (`WHERE`):<\/b> Пишите максимально конкретные фильтры. DuckDB автоматически проталкивает их в сканеры Parquet и Iceberg. Используйте `EXPLAIN` для проверки того, что фильтры применяются на этапе сканирования.<\/li>\n<\/ul>\n<h5>2. Оптимизация SQL-запросов<\/h5>\n<ul>\n<li><b>Материализация промежуточных результатов:<\/b> Если вы делаете несколько агрегаций над одним и тем же отфильтрованным срезом, сохраните его во временную таблицу с помощью `CREATE TEMP TABLE ... AS`.<\/li>\n<li><b>Используйте `COPY` для массовой загрузки:<\/b> При загрузке данных в DuckDB `COPY` на порядки быстрее, чем `INSERT`.<\/li>\n<li><b>Предварительная агрегация:<\/b> Для сверхбольших данных создавайте “витрины” с помощью Trino (см. выше) или DuckDB, а запросы стройте уже по ним.<\/li>\n<\/ul>\n<h5>3. Настройка окружения DuckDB<\/h5>\n<ul>\n<li><b>Управление памятью:<\/b> `SET memory_limit = ‘1GB’;` — обязательная настройка в Lambda и контейнерах.<\/li>\n<li><b>Параллелизм:<\/b> `SET threads = 4;` — адаптируйте количество потоков под vCPU вашего окружения.<\/li>\n<li><b>Настройка `httpfs` для S3:<\/b> Настройте регион (`s3_region`), креды и включите кэширование метаданных, чтобы не перечитывать их при каждом запуске. ( Это комьюнити дополнение -<a href=\"https:\/\/duckdb.org\/community_extensions\/extensions\/cache_httpfs.html\">cache_httpfs<\/a>, см. ниже “Проблема Шторм” )<\/li>\n<\/ul>\n<p>Еще вот тут можно почитать: <a href=\"https:\/\/duckdb.org\/docs\/stable\/guides\/performance\/how_to_tune_workloads\">https:\/\/duckdb.org\/docs\/stable\/guides\/performance\/how_to_tune_workloads<\/a><\/p>\n<h4>Заключение: Какой подход выбрать?<\/h4>\n<p>Выбор архитектуры зависит от вашей задачи. Каждая из них занимает свою нишу в стеке современной инженерии данных.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Подход<\/td>\n<td style=\"text-align: center\">Ключевая технология<\/td>\n<td style=\"text-align: center\">Когда использовать<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Табличный формат<\/b><\/td>\n<td style=\"text-align: center\"><b>Trino (Подготовка) + DuckDB\/Iceberg (Потребление)<\/b><\/td>\n<td style=\"text-align: center\"><b>Стандарт для Lakehouse.<\/b> Нужна строгая структура, надежность и максимальная производительность для аналитических SQL-запросов от различных инструментов.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>RPC-стриминг<\/b><\/td>\n<td style=\"text-align: center\"><b>DuckDB + Arrow Flight<\/b><\/td>\n<td style=\"text-align: center\">Нужен <b>быстрый интерактивный SQL-доступ<\/b> к удаленному экземпляру DuckDB, например, для дашборда или кастомного клиента.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>API поверх данных<\/b><\/td>\n<td style=\"text-align: center\"><b>ROAPI + DataFusion<\/b><\/td>\n<td style=\"text-align: center\">Нужно <b>быстро и без кода<\/b> поднять стандартный `REST`\/`GraphQL` API поверх наборов данных для прототипирования или простых микросервисов.<\/td>\n<\/tr>\n<\/table>\n<hr \/>\n<h4>Проблема Шторм из GET-запросов к S3<\/h4>\n<p>Давайте представим, что вы выполняете запрос к таблице Iceberg или просто к набору из 1000 файлов Parquet на S3:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">SELECT count(*)\nFROM read_parquet('s3:\/\/my-bucket\/data\/*.parquet')\nWHERE event_type = 'click';<\/code><\/pre><p>Чтобы выполнить этот запрос с максимальной эффективностью (с “проталкиванием предиката”), DuckDB должен сделать следующее, *прежде чем* читать основные данные:<\/p>\n<ol start=\"1\">\n<li>Получить список всех 1000 файлов.<\/li>\n<li>Для <b>каждого<\/b> из 1000 файлов прочитать его <b>метаданные (футер)<\/b>. Футер Parquet-файла — это небольшой блок в конце файла, содержащий схему и, что самое важное, статистику по колонкам (min\/max значения).<\/li>\n<li>Проанализировав футер, DuckDB понимает, может ли в этом файле вообще содержаться `event_type = ‘click’`. Если статистика говорит, что в файле есть только типы `’view’` и `’purchase’`, утка его пропустит.<\/li>\n<\/ol>\n<p>Проблема в том, что для чтения футера каждого файла DuckDB должен отправить отдельный HTTP `GET` запрос с указанием диапазона байт (range request) к S3. То есть, один SQL-запрос порождает <b>1000+ мелких HTTP-запросов<\/b>. Это может быть медленно и может быть дорого, так как в S3 вы платите за каждый `GET` запрос.<\/p>\n<p><b>Кэширование метаданных решает именно эту проблему:<\/b> оно сохраняет результаты этих мелких запросов на локальный диск, чтобы при повторном обращении к тем же файлам DuckDB брал их из локального кэша, а не летел снова в S3.<\/p>\n<h4>Решение: Комьюнити-расширение `cache_httpfs`<\/h4>\n<p>Для реализации постоянного, дискового кэширования в DuckDB используется специальное комьюнити-расширение `cache_httpfs`. Оно работает как “обертка” над стандартным `httpfs`.<\/p>\n<p><b>Основная идея:<\/b> Вы говорите DuckDB использовать `cache_httpfs` в качестве клиента для HTTP-запросов. Этот клиент сначала проверяет, нет ли уже нужного блока данных (например, футера Parquet-файла) в локальном кэше. Если есть — отдает его мгновенно. Если нет — идет в S3, скачивает блок, сохраняет его в кэш и отдает DuckDB.<\/p>\n<p>Вот как это настроить:<\/p>\n<h5>Шаг 1: Установка и загрузка расширений<\/h5>\n<p>Вам понадобятся три расширения: `httpfs` (для работы с S3), `cache_httpfs` (для кэширования) и, если вы работаете с Iceberg, то и `iceberg`.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">INSTALL httpfs;\nINSTALL cache_httpfs;\nLOAD httpfs;\nLOAD cache_httpfs;<\/code><\/pre><h5>Шаг 2: Активация кэширующего клиента<\/h5>\n<p>Это ключевой шаг. Вы должны указать DuckDB использовать `cache_httpfs` для всех HTTP-операций.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">SET httpfs_client = 'cached_httpfs';<\/code><\/pre><h5>Шаг 3: Настройка пути к кэшу (критически важно для Serverless)<\/h5>\n<p>По умолчанию `cache_httpfs` сохраняет кэш в директорию `~\/.cache\/duckdb\/`. Это хорошо работает на локальной машине, но в serverless-окружениях (AWS Lambda, Cloud Functions) эта папка либо недоступна для записи, либо является эфемерной.<\/p>\n<p>В serverless-среде единственное гарантированно доступное для записи место — это директория `\/tmp`.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">SET cache_httpfs_cache_path = '\/tmp\/duckdb_cache';<\/code><\/pre><p>Этот кэш в `\/tmp` будет “жить” между “теплыми” вызовами вашей Lambda-функции. Если одна и та же функция вызывается несколько раз подряд, второй и последующие вызовы будут использовать уже заполненный кэш, что кардинально ускорит выполнение запросов к одним и тем же данным.<\/p>\n<h4>Полный пример конфигурации (Python)<\/h4>\n<pre class=\"e2-text-code\"><code class=\"\">import duckdb\n\n# Подключаемся к базе данных\ncon = duckdb.connect()\n\n# Устанавливаем и загружаем расширения\ncon.execute(&quot;INSTALL httpfs;&quot;)\ncon.execute(&quot;INSTALL cache_httpfs;&quot;)\ncon.execute(&quot;LOAD httpfs;&quot;)\ncon.execute(&quot;LOAD cache_httpfs;&quot;)\n\n# --- Настройка S3 и кэша ---\n\n# 1. Настройте креды для S3 (если не используются IAM-роли)\n# con.execute(&quot;SET s3_access_key_id='YOUR_KEY';&quot;)\n# con.execute(&quot;SET s3_secret_access_key='YOUR_SECRET';&quot;)\ncon.execute(&quot;SET s3_region='us-east-1';&quot;)\n\n# 2. Активируем кэширующий http-клиент\ncon.execute(&quot;SET httpfs_client = 'cached_httpfs';&quot;)\n\n# 3. Указываем путь к директории кэша (обязательно для serverless)\ncon.execute(&quot;SET cache_httpfs_cache_path = '\/tmp\/duckdb_http_cache';&quot;)\n\n# --- Выполняем запрос ---\n\n# Первый запуск этого запроса будет медленнее,\n# так как он заполнит кэш метаданными файлов.\nresult1 = con.execute(&quot;SELECT count(*) FROM 's3:\/\/my-bucket\/data\/*.parquet'&quot;).fetchone()\nprint(f&quot;Первый запуск: {result1[0]}&quot;)\n\n# Второй запуск будет на порядки быстрее,\n# так как все метаданные будут прочитаны из локального кэша в \/tmp.\nresult2 = con.execute(&quot;SELECT count(*) FROM 's3:\/\/my-bucket\/data\/*.parquet'&quot;).fetchone()\nprint(f&quot;Второй запуск (с кэшем): {result2[0]}&quot;)<\/code><\/pre><h4>Сравнение: Встроенный кэш vs `cache_httpfs`<\/h4>\n<p>Стоит отметить, что стандартный `httpfs` тоже имеет небольшой *внутренний, оперативный кэш*, но его возможности ограничены.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Параметр<\/td>\n<td style=\"text-align: center\">Встроенный кэш `httpfs`<\/td>\n<td style=\"text-align: center\">Расширение `cache_httpfs`<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Тип<\/b><\/td>\n<td style=\"text-align: center\">Внутренний, в памяти<\/td>\n<td style=\"text-align: center\">Явный, на диске<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Жизненный цикл<\/b><\/td>\n<td style=\"text-align: center\">Живет <b>в рамках одного соединения<\/b> (connection). При переподключении кэш пуст.<\/td>\n<td style=\"text-align: center\">Живет <b>между сессиями и процессами<\/b>. Сохраняется на диске до очистки.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Назначение<\/b><\/td>\n<td style=\"text-align: center\">Ускорение повторных запросов в одной и той же длительной сессии.<\/td>\n<td style=\"text-align: center\"><b>Радикальное ускорение<\/b> для любых повторных запросов, особенно в serverless (warm starts) и при локальной разработке.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Активация<\/b><\/td>\n<td style=\"text-align: center\">Включен по умолчанию<\/td>\n<td style=\"text-align: center\">Требует `SET httpfs_client = ‘cached_httpfs’;`<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Настройка<\/b><\/td>\n<td style=\"text-align: center\">Не настраивается<\/td>\n<td style=\"text-align: center\">Настраивается путь (`cache_httpfs_cache_path`) и максимальный размер.<\/td>\n<\/tr>\n<\/table>\n<p>Для серьезной работы с данными на S3, особенно в serverless-архитектуре, использование расширения `cache_httpfs` является приятным дополнением и зачастую обязательным. Это та самая “серебряная пуля”, которая убирает узкое место в виде задержек сети и большого количества API-вызовов к облачному хранилищу.<\/p>\n<p>Начиная с тяжелых ETL-процессов на Trino и заканчивая быстрыми запросами в DuckDB, современный стек данных предлагает невероятную гибкость и производительность. Выбрав правильный инструмент или их комбинацию для каждой задачи, можно построить по-настоящему эффективную и масштабируемую аналитическую платформу.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/duck.png\" width=\"198\" height=\"149\" alt=\"\" \/>\n<div class=\"e2-text-caption\">pic. Krenskiy Dmitriy<\/div>\n<\/div>\n",
            "date_published": "2025-09-09T01:48:12+03:00",
            "date_modified": "2025-09-09T09:14:51+03:00",
            "tags": [
                "big data",
                "Data Engineer",
                "Data Visualization",
                "datafusion",
                "Programming"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-09-09-v-01.35.35.png",
            "_date_published_rfc2822": "Tue, 09 Sep 2025 01:48:12 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "279",
            "_rss_enclosures": [
                {
                    "url": "https:\/\/gavrilov.info\/video\/-5436782684090959843.mp4",
                    "type": "video\/mp4",
                    "length": 2206521
                }
            ],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-09-09-v-01.35.35.png",
                    "https:\/\/gavrilov.info\/pictures\/image-212.png",
                    "https:\/\/gavrilov.info\/pictures\/duck.png"
                ]
            }
        },
        {
            "id": "262",
            "url": "https:\/\/gavrilov.info\/all\/ekosistema-instrumentov-dlya-data-science-i-ai-ot-dashbordov-do\/",
            "title": "Экосистема инструментов для Data Science и AI: От Дашбордов до Продвинутого MLOps",
            "content_html": "<p>Все это можно быстро и просто запустить тут: <a href=\"https:\/\/www.ploomber.io\">https:\/\/www.ploomber.io<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-08-10-v-23.32.24.png\" width=\"550\" height=\"564\" alt=\"\" \/>\n<\/div>\n<p>В современной науке о данных и разработке искусственного интеллекта недостаточно просто создать модель в Jupyter Notebook ( о нем вы уже знаете ) . Настоящая ценность раскрывается, когда результатами можно поделиться, когда модели становятся интерактивными и когда они надежно развернуты в производственной среде. Для решения этих задач появилось множество фреймворков, каждый со своими сильными сторонами и философией.<\/p>\n<p>В этой статье мы рассмотрим и оценим ключевые инструменты, которые позволяют дата-сайентистам и ML-инженерам создавать веб-приложения, чат-ботов, API, отчеты и управлять жизненным циклом моделей.<\/p>\n<h4>Категория 1: Фреймворки для создания веб-приложений и дашбордов<\/h4>\n<p>Это самая многочисленная группа, предназначенная для быстрого превращения данных и моделей в интерактивные пользовательские интерфейсы без необходимости глубокого изучения фронтенд-технологий.<\/p>\n<h5><b>Streamlit<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 40.8k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/streamlit.io\/\">streamlit.io<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/streamlit\/streamlit\">streamlit<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Streamlit — это, возможно, самый популярный фреймворк для быстрого создания data-приложений. Его философия — превратить скрипты в красивые веб-интерфейсы с минимальными усилиями. Приложение работает по простой модели: скрипт выполняется сверху вниз при каждом взаимодействии пользователя, что упрощает управление состоянием.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Невероятная простота и скорость разработки. Идеально подходит для создания прототипов, демо и внутренних инструментов <a href=\"https:\/\/medium.com\/@anna.bildea\/choosing-the-right-ui-framework-for-genai-projects-54177640b9ca\">medium.com<\/a>. Отличная документация и большое сообщество.<\/li>\n<li><b>Слабые стороны:<\/b> Модель “перезапуска всего скрипта” может быть неэффективной для сложных приложений с большим количеством состояний. Кастомизация интерфейса за пределами стандартных компонентов может быть сложной задачей <a href=\"https:\/\/ai.gopubby.com\/top-5-python-frontend-libraries-for-data-science-91261a65e366?gi=b10c3467a931\">ai.gopubby.com<\/a>.<\/li>\n<\/ul>\n<h5><b>Dash<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 23.9k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/plotly.com\/dash\/\">plotly.com\/dash<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/plotly\/dash\">github.com\/plotly\/dash<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Dash от создателей Plotly — это мощный фреймворк для создания аналитических веб-приложений. Он использует Flask, Plotly.js и React.js под капотом, предоставляя Python-разработчикам доступ к современным веб-технологиям.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Высокая степень кастомизации и контроля. Идеален для корпоративных дашбордов и сложных приложений, требующих уникального дизайна и функциональности. Отличная интеграция с экосистемой Plotly.<\/li>\n<li><b>Слабые стороны:<\/b> Более высокий порог вхождения по сравнению со Streamlit. Концепция “коллбэков” требует времени для освоения.<\/li>\n<\/ul>\n<h5><b>Solara<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 2.1k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/solara.dev\/\">solara.dev<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/widgetti\/solara\">github.com\/widgetti\/solara<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Solara позволяет создавать веб-приложения на чистом Python, используя компонентный подход, похожий на React. Он построен на базе Ipywidgets и может работать как в Jupyter Notebook, так и в виде самостоятельных приложений.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Компонентная архитектура способствует созданию чистого и переиспользуемого кода. Хорошо подходит для создания масштабируемых приложений корпоративного уровня <a href=\"https:\/\/ai.gopubby.com\/top-5-python-frontend-libraries-for-data-science-91261a65e366?gi=b10c3467a931\">ai.gopubby.com<\/a>.<\/li>\n<li><b>Слабые стороны:<\/b> Менее известен, чем Streamlit или Dash, что означает меньшее сообщество и меньше готовых решений.<\/li>\n<\/ul>\n<h5><b>Gradio<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 39.4k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/gradio.app\/\">gradio.app<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/gradio-app\/gradio\">github.com\/gradio-app\/gradio<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Gradio создан для невероятно быстрого создания демо для моделей машинного обучения. Всего за несколько строк кода можно обернуть любую Python-функцию (например, предсказание модели) в простой веб-интерфейс.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Максимальная простота для демонстрации моделей. Поддерживает различные типы ввода\/вывода (текст, изображения, аудио). Легко встраивается в Jupyter\/Colab и генерирует публичные ссылки для демонстрации.<\/li>\n<li><b>Слабые стороны:<\/b> Не предназначен для создания сложных, многостраничных дашбордов. Фокус смещен на “вход -> модель -> выход”. Структура приложения `app.py` часто используется для бэкенда при создании мультимодальных инструментов <a href=\"https:\/\/ai.plainenglish.io\/beyond-text-building-a-fully-multimodal-ai-tool-images-speech-rag-together-8fe4cb322c64?gi=47624379873a&source=rss----78d064101951---4\">ai.plainenglish.io<\/a>.<\/li>\n<\/ul>\n<h5><b>Shiny for Python & Shiny Express<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 1.6k+ (Python)<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/shiny.posit.co\/py\/\">shiny.posit.co\/py<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/posit-dev\/py-shiny\">github.com\/posit-dev\/py-shiny<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Shiny, легендарный фреймворк из мира R, теперь доступен и для Python. Он использует реактивную модель программирования, где изменения во входных данных автоматически вызывают пересчет связанных с ними выходных данных. <b>Shiny Express<\/b> — это его более легковесная версия в стиле Streamlit, позволяющая создавать приложения декларативно.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Мощная реактивная модель позволяет создавать очень эффективные приложения. Отличная интеграция с инструментами от Posit (ранее RStudio).<\/li>\n<li><b>Слабые стороны:<\/b> Сообщество в Python пока меньше, чем у аналогов. Реактивная модель требует особого подхода к мышлению.<\/li>\n<\/ul>\n<h5><b>Panel<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 5.4k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/panel.holoviz.org\/\">panel.holoviz.org<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/holoviz\/panel\">github.com\/holoviz\/panel<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Panel — это мощный фреймворк из экосистемы HoloViz. Его главная особенность — совместимость практически с любой библиотекой для визуализации в Python. Он позволяет объединять виджеты и графики в гибкие макеты.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Непревзойденная гибкость и совместимость с другими библиотеками. Отлично подходит, если вы уже используете инструменты HoloViz (hvPlot, HoloViews).<\/li>\n<li><b>Слабые стороны:<\/b> Может показаться более многословным и сложным для простых задач по сравнению со Streamlit.<\/li>\n<\/ul>\n<h5><b>Другие интересные фреймворки UI<\/b><\/h5>\n<ul>\n<li><b>Chainlit (10k+ звезд):<\/b> Специализированный фреймворк для быстрого создания чат-интерфейсов для LLM-агентов и приложений на базе LangChain\/LlamaIndex.<\/li>\n<li><b>Hyperdiv (900+ звезд):<\/b> Предлагает новый подход: Python-код выполняется на сервере и мгновенно синхронизирует UI в браузере. Компоненты объявляются в простом, декларативном стиле.<\/li>\n<li><b>Vizro (3k+ звезд):<\/b> Конфигурационный фреймворк поверх Dash. Позволяет создавать дашборды через YAML или Pydantic-модели, что упрощает разработку.<\/li>\n<li><b>Voilà (5.8k+ звезд):<\/b> Превращает Jupyter-ноутбуки в самостоятельные веб-приложения, скрывая код и оставляя только виджеты и выводы ячеек.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Категория 2: Бэкенд и MLOps (Развертывание и управление)<\/h4>\n<p>Эти инструменты фокусируются на серверной части, производительности и управлении жизненным циклом моделей.<\/p>\n<h5><b>FastAPI<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 88.2k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/fastapi.tiangolo.com\/\">fastapi.tiangolo.com<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/tiangolo\/fastapi\">github.com\/tiangolo\/fastapi<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> FastAPI — это современный, высокопроизводительный веб-фреймворк для создания API на Python. Он стал де-факто стандартом для развертывания моделей машинного обучения в виде REST API благодаря своей скорости, автоматической документации и использованию стандартных аннотаций типов Python.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Невероятная производительность. Автоматическая интерактивная документация (Swagger UI, ReDoc). Простота использования благодаря Pydantic и аннотациям типов.<\/li>\n<li><b>Слабые стороны:<\/b> Это бэкенд-фреймворк. Для создания UI его нужно использовать в связке с фронтенд-технологиями.<\/li>\n<\/ul>\n<h5><b>vLLM<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 54.8k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/vllm.ai\">vllm.ai<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/vllm-project\/vllm\">github.com\/vllm-project\/vllm<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> vLLM — это не UI-фреймворк, а высокопроизводительная библиотека для инференса (выполнения) больших языковых моделей (LLM). Ее главная цель — максимально увеличить пропускную способность при обслуживании LLM.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Значительно ускоряет работу LLM благодаря инновационным техникам, таким как PagedAttention. Совместимость с моделями Hugging Face. Становится стандартом для быстрого self-hosting LLM.<\/li>\n<li><b>Слабые стороны:<\/b> Узкоспециализированный инструмент для инференса LLM.<\/li>\n<\/ul>\n<h5><b>MLflow<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 21.5k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/mlflow.org\/\">mlflow.org<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/mlflow\/mlflow\">github.com\/mlflow\/mlflow<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> MLflow — это платформа с открытым исходным кодом для управления полным жизненным циклом машинного обучения. Он включает в себя компоненты для отслеживания экспериментов (Tracking), упаковки кода (Projects), управления моделями (Models) и их развертывания (Registry).<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Комплексное решение для MLOps. Помогает стандартизировать и воспроизводить ML-эксперименты. Интегрируется с большинством ML-библиотек.<\/li>\n<li><b>Слабые стороны:<\/b> Требует настройки и внедрения в рабочий процесс. Может быть избыточным для небольших проектов.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Категория 3: Интерактивные вычисления и отчетность<\/h4>\n<p>Эти инструменты меняют представление о статических отчетах и ноутбуках, делая их интерактивными и воспроизводимыми.<\/p>\n<h5><b>Quarto<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 4.7k+ (CLI)<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/quarto.org\/\">quarto.org<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/quarto-dev\/quarto-cli\">github.com\/quarto-dev\/quarto-cli<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Quarto — это система публикации научных и технических документов нового поколения от Posit. Она позволяет создавать динамические документы и презентации из Jupyter-ноутбуков или простого Markdown, смешанного с кодом на Python, R или Julia.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Поддерживает множество форматов вывода (HTML, PDF, DOCX, презентации и др.). Языковая агностичность. Позволяет создавать красивые, профессиональные и воспроизводимые отчеты.<\/li>\n<li><b>Слабые стороны:<\/b> В первую очередь это инструмент для публикации, а не для создания интерактивных real-time приложений.<\/li>\n<\/ul>\n<h5><b>Marimo<\/b><\/h5>\n<ul>\n<li><b>GitHub Stars:<\/b> 15.3k+<\/li>\n<li><b>Официальный сайт:<\/b> <a href=\"https:\/\/marimo.io\/\">marimo.io<\/a><\/li>\n<li><b>GitHub Repo:<\/b> <a href=\"https:\/\/github.com\/marimo-team\/marimo\">github.com\/marimo-team\/marimo<\/a><\/li>\n<\/ul>\n<p><b>Описание и назначение:<\/b> Marimo — это реактивная среда для Python, которая решает многие проблемы традиционных Jupyter-ноутбуков. В Marimo ноутбук — это интерактивное веб-приложение. Изменение в одной ячейке автоматически обновляет все зависимые ячейки.<\/p>\n<p><b>Особенности и оценка:<\/b><\/p>\n<ul>\n<li><b>Сильные стороны:<\/b> Реактивность обеспечивает консистентность состояния. Встроенные UI-элементы. Ноутбуки легко экспортируются в виде приложений.<\/li>\n<li><b>Слабые стороны:<\/b> Новый инструмент с растущим, но пока небольшим сообществом. Отличается от привычного рабочего процесса в Jupyter.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Как выбрать подходящий инструмент?<\/h4>\n<ul>\n<li><b>Для быстрого прототипа или демо модели:<\/b> <b>Streamlit<\/b> или <b>Gradio<\/b>.<\/li>\n<li><b>Для сложного, кастомизированного корпоративного дашборда:<\/b> <b>Dash<\/b> или <b>Solara<\/b>.<\/li>\n<li><b>Для создания бэкенда и API для вашей модели:<\/b> <b>FastAPI<\/b>.<\/li>\n<li><b>Для максимальной производительности при развертывании LLM:<\/b> <b>vLLM<\/b>.<\/li>\n<li><b>Для построения полноценного MLOps-цикла:<\/b> <b>MLflow<\/b>.<\/li>\n<li><b>Для создания чат-бота на базе LLM:<\/b> <b>Chainlit<\/b>.<\/li>\n<li><b>Для создания красивых, воспроизводимых отчетов и статей:<\/b> <b>Quarto<\/b>.<\/li>\n<li><b>Если вы хотите попробовать реактивный, state-of-the-art ноутбук:<\/b> <b>Marimo<\/b>.<\/li>\n<li><b>Если вы из мира R или вам нравится реактивная парадигма:<\/b> <b>Shiny for Python<\/b>.<\/li>\n<\/ul>\n",
            "date_published": "2025-08-10T23:40:36+03:00",
            "date_modified": "2025-08-11T23:37:21+03:00",
            "tags": [
                "AI",
                "Data",
                "Data Visualization",
                "Programming"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-08-10-v-23.32.24.png",
            "_date_published_rfc2822": "Sun, 10 Aug 2025 23:40:36 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "262",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-08-10-v-23.32.24.png"
                ]
            }
        },
        {
            "id": "241",
            "url": "https:\/\/gavrilov.info\/all\/samye-populyarnye-instrumenty-biznes-analitiki-na-osnove-koda-ob\/",
            "title": "Самые популярные инструменты бизнес-аналитики на основе кода: Обзор",
            "content_html": "<p>Сравнение самых популярных BI-as-code инструментов: Evidence, Streamlit, Dash, Observable, Shiny и Quarto<br \/>\nКейси Хуанси Ли – Приглашенный Автор 30 октября 2024 г. · 4 мин чтения<br \/>\nКейси – специалист по данным, инженер-программист и писатель. Ранее она работала в McKinsey & QuantumBlack, а в настоящее время работает в Shopify.<\/p>\n<p>Оригинал тут: <a href=\"https:\/\/evidence.dev\/blog\/business-intelligence-tools\">https:\/\/evidence.dev\/blog\/business-intelligence-tools<\/a><\/p>\n<p>а можно не читать, а идти сразу сюда: <a href=\"https:\/\/gavrilov.info\/all\/tetradki-nashe-vsyo-marimo-io-i-utochkadb\/\">https:\/\/gavrilov.info\/all\/tetradki-nashe-vsyo-marimo-io-i-utochkadb\/<\/a><\/p>\n<p>Не существует единственного «лучшего» инструмента бизнес-аналитики (BI); лучший инструмент для вас зависит от ваших конкретных потребностей, рабочего процесса и набора навыков.<\/p>\n<p>Это руководство сравнивает некоторые из самых популярных инструментов BI-as-code, чтобы помочь вам найти то, что наилучшим образом подходит для вашего стека анализа данных и технических компетенций:<\/p>\n<p>* <b>Evidence:<\/b> Конструктор приложений на Markdown и SQL для аналитиков данных.<br \/>\n* <b>Streamlit:<\/b> Оболочка для веб-приложений для Python-специалистов по данным.<br \/>\n* <b>Dash:<\/b> Фреймворк для веб-приложений для Python-разработчиков.<br \/>\n* <b>Observable:<\/b> Набор инструментов для визуализации данных для JavaScript-разработчиков.<br \/>\n* <b>Shiny:<\/b> Простая R\/Python-оболочка для статистиков и исследователей.<br \/>\n* <b>Quarto:<\/b> Минималистичная система публикации Jupyter\/Markdown для ученых и технических писателей.<\/p>\n<p>Каждый из этих инструментов является открытым исходным кодом, и вы можете найти исходный код на GitHub.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Инструмент<\/td>\n<td>Репозиторий GitHub<\/td>\n<td>Лицензия<\/td>\n<td>Языки<\/td>\n<td>Звезды<\/td>\n<\/tr>\n<tr>\n<td>Evidence<\/td>\n<td>evidence-dev\/evidence<\/td>\n<td>MIT<\/td>\n<td>SQL\/Markdown<\/td>\n<td>4.3k<\/td>\n<\/tr>\n<tr>\n<td>Streamlit<\/td>\n<td>streamlit\/streamlit<\/td>\n<td>Apache 2.0<\/td>\n<td>Python<\/td>\n<td>35k<\/td>\n<\/tr>\n<tr>\n<td>Dash<\/td>\n<td>plotly\/dash<\/td>\n<td>MIT<\/td>\n<td>Python<\/td>\n<td>21k<\/td>\n<\/tr>\n<tr>\n<td>Observable<\/td>\n<td>observablehq\/framework<\/td>\n<td>ISC<\/td>\n<td>JavaScript<\/td>\n<td>2.5k<\/td>\n<\/tr>\n<tr>\n<td>Shiny<\/td>\n<td>rstudio\/shiny<\/td>\n<td>GPL-3.0<\/td>\n<td>R\/Python<\/td>\n<td>5.4k<\/td>\n<\/tr>\n<tr>\n<td>Quarto<\/td>\n<td>quarto-dev\/quarto-cli<\/td>\n<td>MIT<\/td>\n<td>Markdown\/Jupyter<\/td>\n<td>3.9k<\/td>\n<\/tr>\n<\/table>\n<h4>Evidence<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-179.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Инструмент для создания приложений на SQL и Markdown<\/p>\n<p>Evidence выделяется своим управлением входными данными через SQL-запросы и созданием содержимого страниц с помощью Markdown и предварительно созданных компонентов.<\/p>\n<p>Входные данные в Evidence управляются с помощью SQL-запросов. Содержимое страницы создается с помощью Markdown и предварительно созданных компонентов Evidence для общих визуализаций, таких как таблицы или столбчатые диаграммы.<\/p>\n<p>Evidence разработан для аналитиков, знакомых с SQL и Markdown, предлагая расширяемость через веб-стандарты. Приложения Evidence отлаженные, производительные и легко воспринимаются бизнес-стейкхолдерами.<\/p>\n<p>Evidence также предлагает неограниченные возможности для определения ваших собственных пользовательских компонентов с использованием HTML и JavaScript, а также стилизации страниц через CSS. Он также поддерживает постоянно растущий список вариантов развертывания, включая Evidence Cloud — безопасный, управляемый хостинг-сервис.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Sales Report\n\n&lt;Slider min=2019 max=2024 name=year_pick title=Year size=full\/&gt;\n\n```sql sales_by_month\nSELECT\n    order_month,\n    category,\n    sum(sales) AS sales\nFROM orders\nWHERE year = '${inputs.year_pick}'\nGROUP BY ALL\n```\n\n&lt;BarChart\n  data={sales_by_month}\n  title=&quot;Sales by Month&quot;\n  x=order_month\n  y=sales\n\/&gt;<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-180.png\" width=\"1036\" height=\"870\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>Вы в основном работаете с SQL и хотите получать удобные для бизнеса результаты.<\/li>\n<li>Вы не являетесь в первую очередь JavaScript-разработчиком.<\/li>\n<li>Вы хотите иметь возможность добавлять пользовательские компоненты, если ваши потребности выходят за рамки готовой функциональности.<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вы не хотите использовать SQL-запросы для управления входными данными.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Streamlit<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-181.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Веб-приложение-обертка для pandas, numpy и других основных инструментов Python для анализа данных<\/p>\n<p>Если вы уже знакомы с такими вещами, как numpy или pandas, документация Streamlit заставит вас почувствовать себя как дома. Оборачивая, например, `np.histogram` во что-то вроде `st.bar_chart`, Streamlit берет на себя перевод вашего Python-кода в веб-приложение.<\/p>\n<p>Streamlit запускает ваш Python-скрипт сверху вниз, передавая выходные данные, такие как текст, таблицы или диаграммы, на страницу. Этот инструмент также можно использовать для создания чат-бота в стиле ChatGPT с использованием выходных данных на основе Python.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">import streamlit as st\nimport pandas as pd\nimport numpy as np\n\nst.title('Uber pickups in NYC')\n\nDATE_COLUMN = 'date\/time'\nDATA_URL = ('https:\/\/s3-us-west-2.amazonaws.com\/'\n         'streamlit-demo-data\/uber-raw-data-sep14.csv.gz')\n\n@st.cache_data\ndef load_data(nrows):\n    data = pd.read_csv(DATA_URL, nrows=nrows)\n    lowercase = lambda x: str(x).lower()\n    data.rename(lowercase, axis='columns', inplace=True)\n    data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])\n    return data\n\n# Create a text element and let the reader know the data is loading.\ndata_load_state = st.text('Loading data...')\n# Load 10,000 rows of data into the dataframe.\ndata = load_data(10000)\n# Notify the reader that the data was successfully loaded.\ndata_load_state.text(&quot;Done! (using st.cache_data)&quot;)\n\nst.subheader('Raw data')\nst.write(data)\n\nst.subheader('Number of pickups by hour')\n\nhist_values = np.histogram(\n    data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]\n\nst.bar_chart(hist_values)\n\nhour_to_filter = st.slider('hour', 0, 23, 17)  # min: 0h, max: 23h, default: 17h\nfiltered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter]\nst.subheader(f'Map of all pickups at {hour_to_filter}:00')\nst.map(filtered_data)<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-182.png\" width=\"884\" height=\"1480\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>Вы являетесь Python-специалистом по данным, который хочет быстро создать веб-приложение, которым можно поделиться.<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вам нужно настроить UI\/UX, выходя за рамки базовых цветовых тем.<\/li>\n<li>Вам нужен точный контроль над повторной отрисовкой страницы (весь скрипт перезапускается при изменении входных данных, если вы не управляете фрагментами вручную).<\/li>\n<li>Вам не нравится писать Python-скрипты.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Dash<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-183.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Фреймворк для веб-приложений на Python, предоставляющий прямой контроль над макетами, элементами DOM и обратными вызовами.<\/p>\n<p>Dash позволяет Python-разработчикам создавать интерактивные веб-приложения без необходимости изучать JavaScript. Он предлагает существенный контроль и настройку для тех, кто готов углубиться в документацию. Ядро Dash — это класс Python, который объединяет несколько концепций:<\/p>\n<ul>\n<li>Python-обертки для отображения общих элементов DOM и визуализаций plotly (например, `html.H1`, `dcc.Graph`);<\/li>\n<li>Макет приложения, определенный как список вышеуказанных элементов в `app.layout`;<\/li>\n<li>Загрузка и обработка данных с помощью обычных средств анализа данных, таких как numpy или pandas;<\/li>\n<li>Интерактивность посредством обратных вызовов, которые принимают именованные входные данные из приложения (например, значение из выпадающего списка) и возвращают именованные выходные данные (например, отфильтрованный DataFrame);<\/li>\n<li>Возможность добавлять собственный CSS и JavaScript при необходимости.<\/li>\n<\/ul>\n<p>Dash построен на базе Flask, поэтому любой Python-разработчик, имеющий опыт работы с веб-фреймворками, должен чувствовать себя в нем комфортно. Хотя R, Julia и F# также указаны как совместимые языки, подавляющее большинство документации Dash написано для Python.<\/p>\n<p>Dash — мощный выбор для опытных программистов на Python, которым нужен точный контроль. Однако, если вам неудобны ментальные модели, такие как классы, обратные вызовы или DOM, кривая обучения в Dash может показаться несколько крутой.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">from dash import Dash, html, dcc, callback, Output, Input\nimport plotly.express as px\nimport pandas as pd\n\ndf = pd.read_csv('https:\/\/raw.githubusercontent.com\/plotly\/datasets\/master\/gapminder_unfiltered.csv')\n\napp = Dash()\n\napp.layout = [\n    html.H1(children='Title of Dash App', style={'textAlign':'center'}),\n    dcc.Dropdown(df.country.unique(), 'Canada', id='dropdown-selection'),\n    dcc.Graph(id='graph-content')\n]\n\n@callback(\n    Output('graph-content', 'figure'),\n    Input('dropdown-selection', 'value')\n)\ndef update_graph(value):\n    dff = df[df.country==value]\n    return px.line(dff, x='year', y='pop')\n\nif __name__ == '__main__':\n    app.run(debug=True)<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-184.png\" width=\"1514\" height=\"1296\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>У вас сильные навыки Python, и вы хотите более прямого контроля над макетом, стилизацией и интерактивностью, чем в Streamlit.<\/li>\n<li>Вы уже хорошо работаете с веб-фреймворками на базе Python, такими как Flask или Django.<\/li>\n<li>Вы знакомы с библиотеками для анализа данных на базе Python, такими как pandas, numpy и plotly.<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вам неудобно работать с классами, обратными вызовами, методами или декораторами Python.<\/li>\n<li>Вам неудобно напрямую взаимодействовать с DOM.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Observable Framework<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-185.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Инструментарий для визуализации данных для веб-разработчиков на JavaScript.<\/p>\n<p>Если `npm run dev` — это ваша скорость, Observable Framework — отличный выбор для использования всей мощи веб-разработки при визуализации данных. Предоставляя вам импортируемые вспомогательные элементы, такие как Plot и FileAttachment, Observable упрощает интеграцию входных данных и предварительно созданных компонентов визуализации в ваше веб-приложение. У вас по-прежнему есть все обычные инструменты веб-разработки: HTML, JSX, компоненты React, стили CSS, функции JavaScript и импорты и т.д.<\/p>\n<p>Хотя загрузчики данных для Observable могут быть написаны на любом языке программирования, базовый уровень комфорта с концепциями веб-разработки (например, HTML, CSS и JavaScript) позволит вам наилучшим образом использовать многие функции Observable.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">import * as Plot from 'npm:@observablehq\/plot';\n\nexport function temperaturePlot(data, { width } = {}) {\n\treturn Plot.plot({\n\t\ttitle: 'Hourly temperature forecast',\n\t\twidth,\n\t\tx: { type: 'utc', ticks: 'day', label: null },\n\t\ty: { grid: true, inset: 10, label: 'Degrees (F)' },\n\t\tmarks: [\n\t\t\tPlot.lineY(data.properties.periods, {\n\t\t\t\tx: 'startTime',\n\t\t\t\ty: 'temperature',\n\t\t\t\tz: null, \/\/ varying color, not series\n\t\t\t\tstroke: 'temperature',\n\t\t\t\tcurve: 'step-after'\n\t\t\t})\n\t\t]\n\t});\n}\n# Weather report\n\nimport { temperaturePlot } from '.\/components\/temperaturePlot.js';<\/code><\/pre><pre class=\"e2-text-code\"><code class=\"\">const forecast = FileAttachment('.\/data\/forecast.json').json();<\/code><\/pre><pre class=\"e2-text-code\"><code class=\"\">display(temperaturePlot(forecast));<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-186.png\" width=\"1908\" height=\"1492\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>Вы веб-разработчик, который разбирается в HTML, CSS и JavaScript и хочет в полной мере использовать свои обычные инструменты (например, Node, React).<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вы не уверены, что такое node и npm, или что означает async\/await.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Shiny<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-187.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Авторитетная оболочка для R и Python, с акцентом на эффективную реактивность.<\/p>\n<p>Если R или Python — ваш основной язык для анализа данных, и вы не заинтересованы в полноценной веб-разработке или ручном управлении обратными вызовами, то, возможно, стоит потрудиться, чтобы изучить ментальные модели Shiny. Из всех инструментов, рассмотренных в этой статье, он, вероятно, наиболее авторитетен в плане создания новых, специфичных для Shiny концепций, которые должен освоить пользователь. Например, все пользовательские входы (т.е. выпадающие списки) определяются с помощью функций `ui.input_*()`, а все выходы создаются декораторами, такими как `@render.plot`. Даже для опытного Python-разработчика понимание всех этих концепций может занять время. Код для сложной панели инструментов Shiny может стать довольно громоздким.<\/p>\n<p>Преимущество всего этого заключается в том, что Shiny автоматически эффективно управляет реактивностью за вас. Их документация даже приводит пример воспроизведения панели инструментов Streamlit для более быстрой работы.<\/p>\n<p>HTML, CSS и JavaScript могут управляться вручную, но необходимость их размещения внутри Python-оберток может привести к тому, что код будет выглядеть немного громоздко.<\/p>\n<p>Если вы довольны использованием чистых, минималистичных, предварительно стилизованных компонентов Shiny и цените эффективную реактивность, Shiny может быть хорошим выбором.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">from shiny.express import input, render, ui\nfrom shinywidgets import render_plotly\n\nui.page_opts(title=&quot;Penguins dashboard&quot;, fillable=True)\n\nwith ui.sidebar():\n    ui.input_selectize(\n        &quot;var&quot;, &quot;Select variable&quot;,\n        [&quot;bill_length_mm&quot;, &quot;bill_depth_mm&quot;, &quot;flipper_length_mm&quot;, &quot;body_mass_g&quot;, &quot;year&quot;]\n    )\n    ui.input_numeric(&quot;bins&quot;, &quot;Number of bins&quot;, 30)\n\nwith ui.card(full_screen=True):\n    @render_plotly\n    def hist():\n        import plotly.express as px\n        from palmerpenguins import load_penguins\n        return px.histogram(load_penguins(), x=input.var(), nbins=input.bins())<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-188.png\" width=\"1140\" height=\"1006\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>У вас сильные навыки R или Python, и вы хотите использовать только эти языки.<\/li>\n<li>Вы цените быструю, эффективную реактивность и не хотите вручную управлять обратными вызовами.<\/li>\n<li>Вам нравится использовать чистые, минималистичные, предварительно стилизованные компоненты.<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вы не хотите изучать специфические для Shiny ментальные модели для управления UI и реактивностью.<\/li>\n<li>Вы предпочитаете напрямую контролировать UI с помощью более традиционного стека веб-разработки (например, HTML \/ CSS \/ JS).<\/li>\n<li>Вам требуется очень тонкий контроль над внешним видом и ощущениями.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Quarto<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-189.png\" width=\"1300\" height=\"700\" alt=\"\" \/>\n<\/div>\n<p>Минималистичный рендерер страниц на Jupyter \/ Markdown, предназначенный для научной и технической публикации.<\/p>\n<p>Если ваша цель — как можно быстрее и без излишеств преобразовать результаты анализа данных в HTML-файлы, .doc или PDF, Quarto может быть хорошим выбором. Quarto берет заметки Jupyter или Markdown в стиле Quarto и преобразует их в широкий спектр форматов. Доступны темы, а также некоторые параметры интерактивности. Фактически, если вы готовы потрудиться и изучить ее, Quarto предоставляет документацию для большинства задач, которые вы можете захотеть выполнить. В целом, однако, Quarto — хороший выбор для тех, кто уже знаком с заметками Jupyter и хочет быстро представить свою работу в общем формате без чрезмерной настройки или суеты.<\/p>\n<p>Если вы привыкли публиковать свои работы в LaTeX, Quarto также может показаться более современной, гибкой альтернативой, которая по-прежнему предлагает чистый, простой, академический вид документа LaTeX.<\/p>\n<p><b>Пример кода:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">---\ntitle: 'Quarto Basics'\nformat:\n  html:\n    code-fold: true\njupyter: python3\n---<\/code><\/pre><p>For a demonstration of a line plot on a polar axis, see @fig-polar.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">#| label: fig-polar\n#| fig-cap: &quot;A line plot on a polar axis&quot;\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nr = np.arange(0, 2, 0.01)\ntheta = 2 * np.pi * r\nfig, ax = plt.subplots(\n  subplot_kw = {'projection': 'polar'}\n)\nax.plot(theta, r)\nax.set_rticks([0.5, 1, 1.5, 2])\nax.grid(True)\nplt.show()<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-190.png\" width=\"1654\" height=\"1534\" alt=\"\" \/>\n<\/div>\n<p><b>Хороший выбор, если:<\/b><\/p>\n<ul>\n<li>Вы уже знакомы с заметками Jupyter или Markdown и хотите быстро представить свою работу в общем формате с минимальной стилизацией.<\/li>\n<li>Вы не против изучать документацию для выполнения более сложных задач (например, пользовательские темы или развертывание в определенном сервисе, таком как Netlify).<\/li>\n<\/ul>\n<p><b>Не рекомендуется, если:<\/b><\/p>\n<ul>\n<li>Вам требуется полноценная функциональность веб-разработки.<\/li>\n<li>Вам нужен обширный контроль над внешним видом и ощущениями, или интерактивностью.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>Заключение<\/h4>\n<p>При выборе инструмента BI-as-code учитывайте технические навыки вашей команды и конкретные потребности:<\/p>\n<p>* <b>Evidence<\/b> идеально подходит для аналитиков, которые в основном работают с SQL и хотят быстро создавать приложения для данных с использованием Markdown.<br \/>\n* <b>Streamlit<\/b> хорошо подходит для Python-специалистов по данным, стремящихся к быстрому прототипированию.<br \/>\n* <b>Dash<\/b> предлагает больше контроля для Python-разработчиков, знакомых с веб-фреймворками.<br \/>\n* <b>Observable<\/b> предоставляет полные возможности веб-разработки для JavaScript-разработчиков.<br \/>\n* <b>Shiny<\/b> подходит для пользователей R\/Python, которым нужно эффективное управление реактивностью.<br \/>\n* <b>Quarto<\/b> идеально подходит для ученых и технических писателей, сосредоточенных на публикации документов.<\/p>\n<p>Если вы хотите попробовать Evidence сами, вы можете начать бесплатно.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/telegram-cloud-photo-size-2-5318760570654164028-y.jpg\" width=\"1280\" height=\"629\" alt=\"\" \/>\n<\/div>\n<p>Evidence можно хостить на huggingface.co, но вот чем лучше в своей закрытой корпоративной среде пока не ясно. думаемс. 🤔<\/p>\n<p>Кстати, вот такая штука еще интересная, но это тема другой статьи <a href=\"https:\/\/tabler.io\/admin-template\">https:\/\/tabler.io\/admin-template<\/a><\/p>\n",
            "date_published": "2025-05-30T22:48:31+03:00",
            "date_modified": "2025-08-08T00:09:53+03:00",
            "tags": [
                "Data",
                "Data Visualization"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-179.png",
            "_date_published_rfc2822": "Fri, 30 May 2025 22:48:31 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "241",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-179.png",
                    "https:\/\/gavrilov.info\/pictures\/image-180.png",
                    "https:\/\/gavrilov.info\/pictures\/image-181.png",
                    "https:\/\/gavrilov.info\/pictures\/image-182.png",
                    "https:\/\/gavrilov.info\/pictures\/image-183.png",
                    "https:\/\/gavrilov.info\/pictures\/image-184.png",
                    "https:\/\/gavrilov.info\/pictures\/image-185.png",
                    "https:\/\/gavrilov.info\/pictures\/image-186.png",
                    "https:\/\/gavrilov.info\/pictures\/image-187.png",
                    "https:\/\/gavrilov.info\/pictures\/image-188.png",
                    "https:\/\/gavrilov.info\/pictures\/image-189.png",
                    "https:\/\/gavrilov.info\/pictures\/image-190.png",
                    "https:\/\/gavrilov.info\/pictures\/telegram-cloud-photo-size-2-5318760570654164028-y.jpg"
                ]
            }
        },
        {
            "id": "193",
            "url": "https:\/\/gavrilov.info\/all\/evolyuciya-biznes-analitiki-ot-monolitnoy-k-komponuemoy-arhitekt\/",
            "title": "Эволюция бизнес-аналитики: от монолитной к компонуемой архитектуре",
            "content_html": "<p>Перевод: <a href=\"https:\/\/www.pracdata.io\/p\/the-evolution-of-business-intelligence-stack\">https:\/\/www.pracdata.io\/p\/the-evolution-of-business-intelligence-stack<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-132.png\" width=\"1336\" height=\"944\" alt=\"\" \/>\n<\/div>\n<p>По мере того, как мы вступаем в 2025 год, область инженерии данных продолжает свою стремительную эволюцию. В этой серии мы рассмотрим преобразующие тенденции, меняющие ландшафт инженерии данных, от новых архитектурных шаблонов до новых подходов к инструментарию.<\/p>\n<p>Это первая часть нашей серии, посвященная эволюции архитектуры бизнес-аналитики (BI).<\/p>\n<p><b>Введение<\/b><\/p>\n<p>Ландшафт бизнес-аналитики (BI) претерпел значительные преобразования в последние годы, особенно в том, как данные представляются и обрабатываются.<\/p>\n<p>Эта эволюция отражает более широкий переход от монолитных архитектур к более гибким, компонуемым решениям, которые лучше отвечают современным аналитическим потребностям.<\/p>\n<p>В этой статье прослеживается эволюция BI-архитектуры через несколько ключевых этапов: от традиционных монолитных систем, через появление безголовой (headless) и бездонной (bottomless**) BI, до последних разработок в области BI-as-Code и встроенной аналитики.<\/p>\n<p>** 😂 👯‍♀️<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/evolyuciya-biznes-analitiki-ot-monolitnoy-k-komponuemoy-arhitekt.png\" width=\"2156\" height=\"222\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Если серьезно, то наверное лучший вариант бескрайний<\/div>\n<\/div>\n<p><b>Традиционная BI-архитектура: Монолитный подход<\/b><\/p>\n<p>Традиционные BI-инструменты были построены как комплексные, тесно связанные системы со значительным акцентом на дизайне пользовательского интерфейса.<\/p>\n<p>Эти системы обеспечивали обширную гибкость благодаря функциональности “кликай и смотри” для нарезки, разделения и группировки данных с использованием различных визуализаций. В своей основе эти системы состояли из трех взаимосвязанных компонентов, которые работали в гармонии для предоставления бизнес-аналитики.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-133.png\" width=\"473\" height=\"487\" alt=\"\" \/>\n<\/div>\n<p>*Традиционный BI-стек*<\/p>\n<p>Серверный уровень служил основой, обрабатывая прием данных из источников OLAP и создавая оптимизированные кубы данных на сервере. Эти кубы содержали предварительно вычисленные измерения, которые позволяли исследовать данные в режиме реального времени.<\/p>\n<p>Работая совместно с серверной частью, клиентский уровень предоставлял интерфейс визуализации, подключаясь к серверной части для доступа к кубам данных и построения панелей мониторинга.<\/p>\n<p>Семантический уровень завершал архитектуру, определяя ключевые показатели эффективности (KPI) и метрики, встроенные в BI-программное обеспечение.<\/p>\n<p><b>Недостатки традиционных BI-инструментов<\/b><\/p>\n<p>Хотя эти традиционные системы были мощными, они имели значительные накладные расходы.<\/p>\n<p>Организациям требовалась существенная инфраструктура для локального развертывания до того, как управляемые облачные BI-сервисы стали более доступными, а стоимость лицензирования часто была непомерно высокой.<\/p>\n<p>Сроки реализации были длительными, даже демонстрации концепции требовали недель настройки и конфигурации. Для предприятий, обслуживающих большую пользовательскую базу, требования к ресурсам были особенно высокими.<\/p>\n<p>Эти фундаментальные ограничения в сочетании с растущей потребностью в гибкости и экономичности вызвали серию архитектурных инноваций в области BI.<\/p>\n<p><b>Появление бездонных (Bottomless) BI-инструментов<\/b><\/p>\n<p>В ответ на эти вызовы появилось новое поколение легких, дезагрегированных BI-инструментов. Заметные решения с открытым исходным кодом, такие как Apache Superset, Metabase и Redash, начали появляться около десяти лет назад, причем Superset, первоначально разработанный в Airbnb, приобрел особую известность в экосистеме.<\/p>\n<p>Эти новые инструменты приняли “безднную” архитектуру, устранив тяжелый серверный уровень, традиционно используемый для вычислений, построения и кеширования объектов куба.<\/p>\n<p>Вместо того чтобы поддерживать свой собственный вычислительный уровень, они полагаются на подключенные исходные движки для запроса и предоставления данных на панели мониторинга во время выполнения. Этот архитектурный сдвиг вводит различные стратегии для обслуживания данных.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-134.png\" width=\"1456\" height=\"1147\" alt=\"\" \/>\n<\/div>\n<p><b>Работа с задержкой запросов<\/b><\/p>\n<p>Отсутствие сервера отчетов представляет собой серьезную проблему для бездонных BI-инструментов: управление задержкой запросов при доступе к данным в режиме реального времени.<\/p>\n<p>Чтобы решить эту проблему, эти инструменты используют несколько стратегий оптимизации. Один из ключевых подходов включает использование предварительно вычисленных агрегатов, хранящихся в основном хранилище данных, что позволяет панелям мониторинга эффективно предоставлять результаты.<\/p>\n<p>Кроме того, такие инструменты, как Superset, реализуют уровни кеширования с использованием Redis для хранения часто используемых наборов данных. Этот механизм кеширования оказывается особенно эффективным: после того, как первоначальный запрос загружает набор данных, последующие визуализации и перезагрузки панели мониторинга могут обращаться к кешированной версии до тех пор, пока не изменятся базовые данные, что значительно сокращает время отклика.<\/p>\n<p>Для компаний, работающих с большими объемами данных, интеграция со специализированными OLAP-движками реального времени, такими как Druid и ClickHouse, обеспечивает аналитические возможности с низкой задержкой.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-135.png\" width=\"1339\" height=\"1173\" alt=\"\" \/>\n<\/div>\n<p><b>Появление универсального семантического слоя<\/b><\/p>\n<p>По мере того, как отрасль стремилась к большей гибкости в своем BI-стеке, переносимый семантический слой, или то, что известно как безголовая (headless) BI, появился в качестве промежуточного шага между традиционными монолитными системами и полностью легкими решениями.<\/p>\n<p>Платформы безголовой BI предоставляют выделенный семантический слой, а некоторые объединяют движок запросов, позволяя организациям использовать любой инструмент визуализации по своему выбору. Этот подход полностью отделяет уровень представления (фронтенд) от семантического слоя.<\/p>\n<p>С помощью таких инструментов, как Cube и MetricFlow (теперь часть dbt Labs), например, организации могут определять свои метрики и модели данных в центральном месте, а затем подключать различные инструменты визуализации, пользовательские приложения или легкие BI-решения к этому семантическому слою.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-136.png\" width=\"542\" height=\"755\" alt=\"\" \/>\n<\/div>\n<p>Этот архитектурный шаблон предлагает несколько преимуществ по сравнению с традиционными BI-системами. Он позволяет организациям поддерживать согласованные определения метрик в различных инструментах визуализации, поддерживает несколько интерфейсных приложений одновременно и обеспечивает лучшие возможности интеграции с современными стеками данных.<\/p>\n<p>Семантический слой действует как универсальный переводчик между источниками данных и уровнями визуализации, обеспечивая согласованную бизнес-логику во всех аналитических приложениях.<\/p>\n<p><b>Движение BI-as-Code<\/b><\/p>\n<p>В последние годы наблюдается появление BI-as-Code, представляющего собой еще более легкий подход к разработке панелей мониторинга и интерактивных приложений для работы с данными.<\/p>\n<p>Этот сдвиг парадигмы привносит рабочие процессы разработки программного обеспечения в разработку BI, позволяя использовать контроль версий, тестирование и методы непрерывной интеграции. Поскольку код служит основной абстракцией, а не пользовательским интерфейсом, разработчики могут реализовывать правильные рабочие процессы разработки перед развертыванием в производственной среде.<\/p>\n<p>Известные инструменты в этой области, такие как Streamlit, легко интегрируются с экосистемой Python, позволяя разработчикам оставаться в рамках своих проектов Python без необходимости установки внешнего программного обеспечения для создания панелей мониторинга и приложений для работы с данными.<\/p>\n<p>Этот подход делает упор на простоту и скорость, используя SQL и декларативные инструменты, такие как YAML, для создания панелей мониторинга. Полученные веб-приложения можно легко разместить самостоятельно, обеспечивая гибкость развертывания.<\/p>\n<p>Хотя Streamlit лидирует по популярности, в последние годы появились новые решения с открытым исходным кодом, такие как Evidence, Rill, Vizro и Quary, каждое из которых привносит свой собственный подход к концепции BI-as-Code.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-137.png\" width=\"688\" height=\"745\" alt=\"\" \/>\n<\/div>\n<p><b>Ограничения BI-as-Code<\/b><\/p>\n<p>Инструменты BI-as-Code в настоящее время имеют ограничения с точки зрения интерактивных функций исследования данных и предоставления BI-возможностей корпоративного уровня.<\/p>\n<p>Они не обеспечивают тот же пользовательский опыт для нарезки и разделения данных, что и традиционные BI-инструменты, и им не хватает поддержки управления данными и семантического слоя, которые есть как в традиционных, так и в легких BI-решениях.<\/p>\n<p>Тем не менее, BI-as-Code все чаще используется различными способами, например, командами специалистов по обработке данных, создающими интерактивные автономные приложения, командами разработчиков продуктов, создающими встроенные функции аналитики, и аналитиками, разрабатывающими внутренние приложения для работы с данными.<\/p>\n<p><b>Новая развивающаяся тенденция: BI + Встроенная аналитика<\/b><\/p>\n<p>Последняя эволюция в BI-архитектуре включает интеграцию высокопроизводительных встраиваемых OLAP-движков запросов, таких как Apache DataFusion и DuckDB.<\/p>\n<p>Этот подход устраняет несколько пробелов в текущем ландшафте, сохраняя при этом преимущества легких, дезагрегированных архитектур.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-138.png\" width=\"1209\" height=\"1094\" alt=\"\" \/>\n<\/div>\n<p>Новая полнофункциональная компонуемая BI-архитектура дает несколько ключевых преимуществ:<\/p>\n<p>Во-первых, она предлагает настоящую компонуемость и совместимость с возможностью замены встроенных вычислительных движков по мере необходимости, сохраняя при этом автономный семантический слой для определения метрик.<\/p>\n<p>Возможности встроенной аналитики особенно мощны благодаря интеграции без копирования через стандартные фреймворки, в основном Apache Arrow, обеспечивающей доступ к данным на уровне микросекунд через оптимизированные столбчатые форматы в памяти.<\/p>\n<p>Интеграция без копирования относится к методу оптимизации производительности, при котором доступ к данным и их обработка могут осуществляться без необходимости сериализации и преобразования данных между различными представлениями в памяти. В контексте DataFusion и Apache Arrow это означает, что когда данные загружаются в память в столбчатом формате Arrow, DataFusion может напрямую выполнять вычисления с этими данными без необходимости их преобразования или копирования во внутренний формат.<\/p>\n<p>Прямая поддержка озер данных и lakehouse представляет собой еще один значительный шаг вперед, позволяя командам создавать панели мониторинга непосредственно поверх открытых табличных форматов, таких как Apache Iceberg и Apache Hudi, без промежуточного перемещения данных.<\/p>\n<p>Эта возможность в сочетании с комплексной поддержкой федеративных запросов решает давнюю проблему в существующих легких BI-инструментах, которые с трудом эффективно объединяли данные из нескольких источников без необходимости использования внешнего движка федеративных запросов.<\/p>\n<p><b>Внедрение в отрасли<\/b><\/p>\n<p>Внедрение встраиваемых движков запросов в отрасли набирает обороты в экосистеме BI.  Коммерческие поставщики возглавляют эту трансформацию: Omni интегрировала DuckDB в качестве своего основного аналитического движка, в то время как Cube.dev реализовала сложное сочетание Apache Arrow и DataFusion в своей безголовой BI-архитектуре.<\/p>\n<p>Аналогичным образом, GoodData приняла эту тенденцию, реализовав Apache Arrow в качестве основы уровня кеширования своей системы FlexQuery, а Preset (Managed Superset) интегрировалась с MotherDuck (Managed DuckDB).<\/p>\n<p>В области открытого исходного кода и Superset (с использованием библиотеки duckdb-engine), и Metabase теперь поддерживают встроенное подключение DuckDB с потенциальной будущей интеграцией в их основные движки.<\/p>\n<p>Движение BI-as-Code также приняло встраиваемые движки. Rilldata объявила об интеграции DuckDB в 2023 году для автоматического профилирования и интерактивного моделирования при разработке панелей мониторинга, в то время как Evidence представила <a href=\"https:\/\/evidence.dev\/blog\/why-we-built-usql\">Universal SQL в 2024 году<\/a>, основанный на реализации WebAssembly от DuckDB.<\/p>\n<p><b>Заключение<\/b><\/p>\n<p>Ландшафт бизнес-аналитики продолжает развиваться в сторону более гибких и эффективных решений.<\/p>\n<p>Каждое архитектурное изменение принесло явные преимущества: безголовая BI обеспечила согласованность метрик между инструментами, бездонная BI снизила сложность инфраструктуры, BI-as-Code привнесла рабочие процессы разработчиков в аналитику, а встроенные движки теперь объединяют эти преимущества с высокопроизводительными возможностями запросов.<\/p>\n<p>Интеграция встраиваемых движков запросов с легкими BI-инструментами представляет собой перспективное направление для реализации легкой BI, объединяющее лучшие аспекты традиционных BI-возможностей с современными архитектурными шаблонами. По мере развития этих технологий и роста экосистемы компании могут рассчитывать на все более сложные, но компонуемые решения для своих аналитических потребностей.<\/p>\n",
            "date_published": "2025-02-13T01:23:28+03:00",
            "date_modified": "2025-02-14T23:09:31+03:00",
            "tags": [
                "BI",
                "Data Mesh",
                "Data Visualization"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-132.png",
            "_date_published_rfc2822": "Thu, 13 Feb 2025 01:23:28 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "193",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-132.png",
                    "https:\/\/gavrilov.info\/pictures\/evolyuciya-biznes-analitiki-ot-monolitnoy-k-komponuemoy-arhitekt.png",
                    "https:\/\/gavrilov.info\/pictures\/image-133.png",
                    "https:\/\/gavrilov.info\/pictures\/image-134.png",
                    "https:\/\/gavrilov.info\/pictures\/image-135.png",
                    "https:\/\/gavrilov.info\/pictures\/image-136.png",
                    "https:\/\/gavrilov.info\/pictures\/image-137.png",
                    "https:\/\/gavrilov.info\/pictures\/image-138.png"
                ]
            }
        },
        {
            "id": "97",
            "url": "https:\/\/gavrilov.info\/all\/bi-kak-kod-rill\/",
            "title": "BI как код – Rill",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/240772792-49d17e80-5f27-408c-bbc9-fdbff7b6b627.gif\" width=\"1782\" height=\"1152\" alt=\"\" \/>\n<div class=\"e2-text-caption\"><a href=\"https:\/\/github.com\/rilldata\/rill\">https:\/\/github.com\/rilldata\/rill<\/a><\/div>\n<\/div>\n<p>Качаем, ставим, запускаем:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">curl -s https:\/\/cdn.rilldata.com\/install.sh | bash\nrill start my-rill-project<\/code><\/pre><p>Можно еще статейку полистать:<br \/>\n<a href=\"https:\/\/a.gavrilov.info\/data\/posts\/Unlocking%20Data%20Insights%20with%20Rill:%20A%20Comprehensive%20Guide%20to%20Streamlined%20Data%20Analytics%20%7C%20by%20Felix%20Gu.pdf\">https:\/\/a.gavrilov.info\/data\/posts\/Unlocking%20Data%20Insights%20with%20Rill:%20A%20Comprehensive%20Guide%20to%20Streamlined%20Data%20Analytics%20%7C%20by%20Felix%20Gu.pdf<\/a><\/p>\n<p>🤌 DuckDB inside<\/p>\n",
            "date_published": "2023-12-14T21:30:52+03:00",
            "date_modified": "2023-12-14T21:30:48+03:00",
            "tags": [
                "as a code",
                "Data Visualization"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/240772792-49d17e80-5f27-408c-bbc9-fdbff7b6b627.gif",
            "_date_published_rfc2822": "Thu, 14 Dec 2023 21:30:52 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "97",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/240772792-49d17e80-5f27-408c-bbc9-fdbff7b6b627.gif"
                ]
            }
        },
        {
            "id": "93",
            "url": "https:\/\/gavrilov.info\/all\/vizualizaciya-izmeneniya-cennosti-1-na-protyazhenii-20-let\/",
            "title": "Визуализация изменения ценности 1$ на протяжении 20 лет",
            "content_html": "<p>Смотрим тут: <a href=\"https:\/\/perthirtysix.com\/tool\/visualizing-american-inflation\">https:\/\/perthirtysix.com\/tool\/visualizing-american-inflation<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2023-12-10-v-22.08.47.png\" width=\"2382\" height=\"1336\" alt=\"\" \/>\n<div class=\"e2-text-caption\"><a href=\"https:\/\/perthirtysix.com\/tool\/visualizing-american-inflation\">https:\/\/perthirtysix.com\/tool\/visualizing-american-inflation<\/a><\/div>\n<\/div>\n<p>Или копию pdf тут: <a href=\"https:\/\/a.gavrilov.info\/data\/posts\/How%20Far%20Would%20\">https:\/\/a.gavrilov.info\/data\/posts\/How%20Far%20Would%20<\/a>$1%20From%201999%20Go%20Today%3F.pdf<\/p>\n",
            "date_published": "2023-12-10T22:17:39+03:00",
            "date_modified": "2023-12-10T22:17:32+03:00",
            "tags": [
                "Data Visualization",
                "Economic"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2023-12-10-v-22.08.47.png",
            "_date_published_rfc2822": "Sun, 10 Dec 2023 22:17:39 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "93",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2023-12-10-v-22.08.47.png"
                ]
            }
        },
        {
            "id": "25",
            "url": "https:\/\/gavrilov.info\/all\/risuyu-prostuyu-diagrammu-na-python\/",
            "title": "Рисую простую диаграмму на Python",
            "content_html": "<p>Вот собственно сам код:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">import pandas as pd\nimport altair as alt\n\ndf = pd.read_excel('Sample - Superstore.xls', index_col=0) \ndf2 = df.groupby('Region').sum()\ndf2 = df2.reset_index(level=0)\n\nbars = alt.Chart(df2).mark_bar().encode(\n   alt.X('Region:N', sort='-y'),\n   alt.Y('Sales:Q'),\n   color=alt.condition(  alt.datum.Region == 'West',  # If the year is 1810 this test returns True,\n   alt.value('orange'),     # which sets the bar orange.\n   alt.value('steelblue'))   \n)\n\ntext = bars.mark_text(\n    align='left',\n    baseline='middle',\n    dx=11  # Nudges text to right so it doesn't appear on top of the bar\n).encode(\n    text='mean(Sales):Q'\n)\n\n(bars + text).properties(height=300)<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/visualization.png\" width=\"209\" height=\"370\" alt=\"\" \/>\n<\/div>\n",
            "date_published": "2022-07-09T19:36:03+03:00",
            "date_modified": "2022-07-09T20:11:14+03:00",
            "tags": [
                "Data Visualization",
                "Python"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/visualization.png",
            "_date_published_rfc2822": "Sat, 09 Jul 2022 19:36:03 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "25",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/visualization.png"
                ]
            }
        }
    ],
    "_e2_version": 4171,
    "_e2_ua_string": "Aegea 11.4 (v4171e)"
}