{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Yuriy Gavrilov: posts tagged big data",
    "_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\/big-data\/",
    "feed_url": "https:\/\/gavrilov.info\/tags\/big-data\/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": "327",
            "url": "https:\/\/gavrilov.info\/all\/arhitektura-client-spooling-kak-bystro-vygruzhat-gigantskie-data\/",
            "title": "Архитектура Client Spooling: Как быстро выгружать гигантские датасеты в Trino и Apache DataFusion",
            "content_html": "<p>Работа с Big Data часто упирается в классическое “узкое горлышко”: кластер может обработать терабайты данных за секунды, но передача результатов (Result Set) обратно на сторону клиента (например, в Jupyter или скрипт) занимает часы. На дворе апрель 2026 года, и современные аналитические движки предлагают эффективные методы обхода этой проблемы — концепцию <b>Spooling<\/b>.<\/p>\n<p>Немного душноты:<\/p>\n<p>Архитектура Client Spooling в Trino создавалась с параноидальным акцентом на безопасность, в S3 выкидываются куски сырых, возможно, чувствительных данных.<\/p>\n<p>Когда Trino решает сбросить данные в объектное хранилище, он всегда шифрует их на лету.<br \/>\nДля этого используется механизм S3 SSE-C (Server-Side Encryption with Customer-provided keys). Trino генерирует уникальный случайный AES-ключ для каждого запроса, отправляет его в MinIO вместе с данными, а клиенту (вашему Jupyter) отдает ссылку + этот же ключ для расшифровки.<br \/>\nЕсли мы используем локальный MinIO по адресу <a href=\"http:\/\/minio:9000\">http:\/\/minio:9000<\/a> (без SSL\/TLS), сервер MinIO видит, что ему пытаются передать секретный пароль (SSE-C ключ) по открытому незащищенному HTTP-каналу.<br \/>\nMinIO (как и настоящий AWS S3) строго запрещает это по спецификации. Он возвращает HTTP 400 Bad Request с ошибкой: “Requests specifying Server Side Encryption... must be made over a secure connection”. Поэтому тестировать лучше на реальном s3. И еще<\/p>\n<p>Мгновенное удаление (Сборка мусора)<\/p>\n<p>Главное правило Client Spooling: Trino удаляет файлы сразу же, как только они были прочитаны клиентом.<br \/>\nКак только ваш Python-скрипт или Jupyter получает ссылку на файл, скачивает его и отправляет координатору Trino HTTP-сигнал (ACK), что кусок получен, координатор дает команду немедленно удалить этот объект из S3.<br \/>\nЕсли запрос отменен или упал с ошибкой, Trino тоже моментально зачищает за собой fs.location. Вы просто не успеете их там увидеть.<\/p>\n<p>Данных слишком мало (Thresholds)<\/p>\n<p>Писать 10 строк в S3, генерировать для них Pre-signed URLs и отдавать клиенту — это дольше, чем просто плюнуть эти 10 строк текстом через координатор. Trino использует эвристику: если Result Set маленький, он отдается “инлайн” (внутри JSON-ответа самого координатора), и S3 не задействуется.<\/p>\n<p>В этой статье мы разберем, как передавать результаты запросов через промежуточное S3-хранилище, на примере движков Trino и Apache DataFusion.<\/p>\n<h4>Физика проблемы и математика Spooling<\/h4>\n<p>В классической архитектуре все воркеры кластера отправляют вычисленные строки на главный узел (Coordinator), а тот уже отдает их по одному каналу клиенту.<\/p>\n<p>Если D — это объем результирующей выборки, а B c — пропускная способность сети координатора, то время выгрузки данных клиенту без спулинга равно:<\/p>\n<p>T classic = B \/ Dc<\/p>\n<p>В режиме <b>Spooling<\/b> координатор не гоняет данные через себя. Воркеры напрямую, параллельно пишут куски результата в дешевое объектное хранилище (S3\/MinIO). Клиент получает лишь ссылки на эти файлы и скачивает их напрямую. Если у нас N файлов в S3, доступных для многопоточного скачивания с пропускной способностью клиента B client: T spooling ≈ min(N×B s3,B client)D<\/p>\n<p>Это позволяет ускорить выгрузку в десятки раз, так как $B_{client}$ и распределенный $B_{s3}$ обычно значительно больше ограничений одного координатора.<\/p>\n<hr \/>\n<h4>Подготовка минимальной инфраструктуры<\/h4>\n<p>Для демонстрации двух подходов мы убрали из нашего кластера все тяжелые клиентские среды (Jupyter, Spark) и оставили только “голое” ядро: хранилище S3, REST-каталог и SQL-движок.<\/p>\n<p><summary><b>минимальный<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker-compose.yml<\/code><\/pre><p><\/b><\/summary><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">version: '3.8'\n\nservices:\n  minio:\n    image: minio\/minio:latest\n    ports:\n      - &quot;19000:9000&quot;\n      - &quot;19001:9001&quot;\n    environment:\n      MINIO_ROOT_USER: &quot;minio-root-user&quot;\n      MINIO_ROOT_PASSWORD: &quot;minio-root-password&quot;\n    command: server \/data --console-address &quot;:9001&quot;\n\n  minio-setup:\n    image: minio\/mc:latest\n    depends_on:\n      - minio\n    entrypoint: &gt;\n      \/bin\/sh -c &quot;\n      sleep 5;\n      mc alias set myminio http:\/\/minio:9000 minio-root-user minio-root-password;\n      mc mb myminio\/warehouse || true;\n      &quot;\n\n  lakekeeper:\n    image: dalongrong\/lakekeeper:latest\n    ports:\n      - &quot;8181:8181&quot;\n    environment:\n      - S3_ENDPOINT=http:\/\/minio:9000\n      - S3_REGION=us-east-1\n      - S3_ACCESS_KEY_ID=minio-root-user\n      - S3_SECRET_ACCESS_KEY=minio-root-password\n    depends_on:\n      - minio-setup\n\n  trino:\n    image: trinodb\/trino:latest\n    ports:\n      - &quot;8080:8080&quot;<\/code><\/pre><p><summary><b>Шаг 1. Настройка каталога и генерация данных (Trino)<\/b><\/summary><br \/>\n<br><br \/>\nСначала мы генерируем данные в Trino. Запрос<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE CATALOG<\/code><\/pre><p>использует динамическое подключение к Lakekeeper REST API. Скрипт записывает файлы в формате Parquet в MinIO:<\/p>\n<p><b>config.properties<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">protocol.spooling.enabled=true\n# 256-битный ключ в формате base64. Вы можете сгенерировать свой с помощью команды `openssl rand -base64 32`\nprotocol.spooling.shared-secret-key=jxTKysfCBuMZtFqUf8UJDQ1w9ez8rynEJsJqgJf66u0=\n\ncatalog.management=dynamic<\/code><\/pre><p><b>spooling-manager.properties<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">spooling-manager.name=filesystem\n# Включаем чтение\/запись в S3 для Spooling\nfs.s3.enabled=true\n# Путь внутри MinIO (указываем через s3:\/\/)\nfs.location=s3:\/\/warehouse\/client-spooling\/\n\n# Системные настройки S3 (MinIO)\ns3.endpoint=http:\/\/minio:9000\ns3.region=us-east-1\ns3.aws-access-key=minio-root-user\ns3.aws-secret-key=minio-root-password\ns3.path-style-access=true<\/code><\/pre><p>-- 1. Подключение каталога Iceberg<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE CATALOG test_warehouse USING iceberg\nWITH (\n    &quot;iceberg.catalog.type&quot; = 'rest',\n    &quot;iceberg.rest-catalog.uri&quot; = 'http:\/\/lakekeeper:8181\/catalog\/',\n    &quot;iceberg.rest-catalog.warehouse&quot; = '00000000-0000-0000-0000-000000000000\/test_warehouse',\n    &quot;iceberg.rest-catalog.security&quot; = 'OAUTH2',\n    &quot;iceberg.rest-catalog.nested-namespace-enabled&quot; = 'true',\n    &quot;iceberg.rest-catalog.vended-credentials-enabled&quot; = 'true',\n    &quot;fs.native-s3.enabled&quot; = 'true',\n    &quot;s3.region&quot; = 'us-east-1',\n    &quot;s3.path-style-access&quot; = 'true',\n    &quot;s3.endpoint&quot; = 'http:\/\/minio:9000'\n);<\/code><\/pre><p>-- 2. Создание структуры<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE SCHEMA test_warehouse.test_schema;\n\nCREATE TABLE test_warehouse.test_schema.my_table (\n    id BIGINT,\n    data VARCHAR\n) WITH (format = 'PARQUET');<\/code><\/pre><p>-- 3. Запись данных<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">INSERT INTO test_warehouse.test_schema.my_table VALUES (1, 'hello'), (2, 'world');<\/code><\/pre><hr \/>\n<p>Если написать Select – должно быть как-то так<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-04-12-v-18.25.52.png\" width=\"490\" height=\"284\" alt=\"\" \/>\n<\/div>\n<h4>Аналог Spooling в Apache DataFusion (Через экспорт)<\/h4>\n<p>Trino поддерживает протокол *Client Spooling* “из коробки” — когда Python-клиент запрашивает огромный `SELECT`, Trino сам незаметно пишет куски в S3 и отдает клиенту готовые ссылки.<\/p>\n<p>В <b>Apache DataFusion<\/b> (который часто работает как локальный движок `datafusion-cli` или встраиваемая библиотка поверх S3) применяется более прозрачный паттерн делегирования (Explicit Spooling). Мы вручную инструктируем движок сохранить результаты агрегации в распределенное хранилище, чтобы позже забрать их в удобном формате — например, упаковав их в `JSON` и сжав алгоритмом `ZSTD`.<\/p>\n<h5>1. Подключение к S3 и маппинг исходной таблицы<\/h5>\n<p>Запускаем `datafusion-cli`, передав доступы как переменные среды (для предотвращения ошибок парсинга опций):<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">AWS_ACCESS_KEY_ID=&quot;minio-root-user&quot; \\\nAWS_SECRET_ACCESS_KEY=&quot;minio-root-password&quot; \\\nAWS_ENDPOINT=&quot;http:\/\/localhost:19000&quot; \\\nAWS_REGION=&quot;us-east-1&quot; \\\nAWS_ALLOW_HTTP=&quot;true&quot; \\\ndatafusion-cli<\/code><\/pre><p>Внутри консоли подключаем директорию с Parquet-файлами, сгенерированными Trino:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE EXTERNAL TABLE my_parquet_data \nSTORED AS PARQUET \nLOCATION 's3:\/\/warehouse\/019d81a3-c2d6-7ed2-ab15-070becf62582\/my_table-13e4b91a2b4e47d98f312b1384263880\/data\/';<\/code><\/pre><h5>2. Массовая конвертация и выгрузка (DataFusion COPY)<\/h5>\n<p>Вместо того чтобы тянуть миллионы строк на локальный терминал, мы просим DataFusion выполнить преобразование и записать итог запроса обратно в MinIO.<\/p>\n<p>Мы выбираем построчный JSON с экстремальным сжатием:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">COPY (\n    -- Тут может быть любая сложная агрегация:\n    -- SELECT id, count(data) FROM my_parquet_data GROUP BY id\n    SELECT * FROM my_parquet_data\n) \nTO 's3:\/\/warehouse\/019d81a3-c2d6-7ed2-ab15-070becf62582\/my_table-13e4b91a2b4e47d98f312b1384263880\/json_export\/' \nSTORED AS JSON\nOPTIONS (\n    'format.compression' 'zstd'\n);<\/code><\/pre><p><b>Результат:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">+-------+\n| count |\n+-------+\n| 2     |\n+-------+\n1 row(s) fetched. \nElapsed 0.270 seconds.<\/code><\/pre><p>За миллисекунды (0.270 sec) DataFusion прочитал партиции, трансформировал бинарные столбцы в текст и сжал его.<\/p>\n<h4>В чем преимущество подхода DataFusion?<\/h4>\n<p>Описанный паттерн выполнения команды `COPY TO` с сохранением `.json.zst` в MinIO полностью воспроизводит механику Spooling:<\/p>\n<ol start=\"1\">\n<li><b>Отсутствие OOM (Out Of Memory):<\/b> Клиент получает только метаданные `count`, а не гигабайты сырых данных в оперативную память.<\/li>\n<li><b>Параллелизм:<\/b> Если исходных файлов много, DataFusion будет писать множество потоков `part-0.json.zst`, `part-1.json.zst` в бакет параллельно.<\/li>\n<li><b>Удаленное потребление:<\/b> Вы можете запустить легкий Python-скрипт (Pandas) на дешевой машине, который просто прочитает эти сжатые легковесные JSON объекты напрямую из MinIO, минуя дорогостоящие вычислительные кластеры.<\/li>\n<\/ol>\n<p>Еще немного про  Fault-Tolerant Execution (FTE), нужно провести важную границу между <b>архитектурой Trino<\/b> (готовый распределенный кластер) и <b>архитектурой DataFusion<\/b> (ядро\/библиотека выполнения запросов).<\/p>\n<p>В самом “голом” ядре DataFusion (которое вы запускаете в `datafusion-cli` или в Jupyter) <b>нет встроенного механизма Task Retries<\/b>, потому что процессы выполняются на одной машине в рамках одного приложения. Если сервер падает — запрос прерывается.<\/p>\n<p>Однако, в экосистеме DataFusion есть механизмы отказоустойчивости, которые делятся на два уровня: <b>локальный (Spilling)<\/b> и <b>распределенный (Apache Ballista \/ Ray)<\/b>.<\/p>\n<hr \/>\n<h4>1. Локальная отказоустойчивость (защита от OOM)<\/h4>\n<p>В Trino частой причиной падения задач является нехватка памяти (Out of Memory). В DataFusion реализован мощный механизм управления памятью.<\/p>\n<p>Если DataFusion понимает, что оперативной памяти для агрегации или JOIN’а не хватает, он не “роняет” задачу, а начинает сбрасывать промежуточные данные на диск (<b>Spill to Disk<\/b>).<\/p>\n<ul>\n<li>Это настраивается через конфигурацию `datafusion.execution.disk_manager`.<\/li>\n<li>Это аналог локального `spill-enabled = true` в Trino. Запрос замедлится, но выполнится до конца, не упав с ошибкой.<\/li>\n<\/ul>\n<h4>2. Распределенная отказоустойчивость (Аналог Trino FTE)<\/h4>\n<p>Trino использует архитектуру <b>Fault-Tolerant Execution (FTE)<\/b>, при которой промежуточные результаты (Shuffle Exchange) пишутся в S3, а упавшие воркеры заменяются, и их задачи (Tasks) перезапускаются координатором.<\/p>\n<p>В мире DataFusion эту задачу решает не само ядро, а <b>распределенные планировщики<\/b>, построенные поверх него:<\/p>\n<h5>А. Apache Ballista (Официальный распределенный DataFusion)<\/h5>\n<p>Ballista — это надстройка над DataFusion, превращающая его в полноценный кластер (с Coordinator и Executors), архитектурно очень похожая на Apache Spark и Trino.<\/p>\n<ul>\n<li><b>Task Retries:<\/b> Если один из Executor’ов теряется из-за сбоя сети или железа, Ballista Coordinator замечает это и <b>переназначает задачу (Task) другому воркеру<\/b>.<\/li>\n<li><b>Shuffle Spilling:<\/b> Промежуточные данные между стадиями (Stages) записываются во временные файлы. Следовательно, если упала только последняя стадия, кластеру не нужно пересчитывать весь запрос с нуля — он прочитает промежуточные Shuffle-файлы и повторит только упавший кусок.<\/li>\n<\/ul>\n<h5>Б. DataFusion on Ray (datafusion-ray)<\/h5>\n<p>Сейчас огромную популярность набирает запуск DataFusion поверх кластера <b>Ray<\/b>.<br \/>\nRay — это супер-устойчивый распределенный фреймворк. Интеграция `datafusion-ray` позволяет разбить SQL-запрос на граф задач прямо в Ray.<\/p>\n<ul>\n<li>За отказоустойчивость, Retry-логику и восстановление упавших узлов (Actor\/Task) здесь отвечает сам Ray, который делает это на уровне индустриального стандарта.<\/li>\n<li>Это максимально близко к концепции отказоустойчивого кластера.<\/li>\n<\/ul>\n<h4>Резюме: Как получить “Trino-like” Fault Tolerance в DataFusion?<\/h4>\n<ol start=\"1\">\n<li>Если вы используете <b>локальный DataFusion<\/b> (в Python или CLI): Отказоустойчивости уровня узлов нет, но есть защита от падений по памяти (Spill to Disk). Если упадет процесс — нужно перезапускать запрос руками.<\/li>\n<li>Если вам нужен настоящий <b>Task Repeat \/ Fault Tolerance<\/b> на сотнях серверов, где падение серверов — норма: вы используете движок DataFusion вместе с кластерным менеджером <b>Apache Ballista<\/b> или <b>Ray<\/b>, которые прозрачно обеспечат перезапуск задач (Retries) и сохранение промежуточных состояний (Shuffle), полностью повторяя логику Trino FTE.<\/li>\n<\/ol>\n",
            "date_published": "2026-04-12T19:11:05+03:00",
            "date_modified": "2026-04-13T00:36:14+03:00",
            "tags": [
                "big data",
                "Data Engineer",
                "datafusion",
                "Trino"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-04-12-v-18.25.52.png",
            "_date_published_rfc2822": "Sun, 12 Apr 2026 19:11:05 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "327",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-04-12-v-18.25.52.png"
                ]
            }
        },
        {
            "id": "323",
            "url": "https:\/\/gavrilov.info\/all\/starrocks-arhitektura-praktika-i-mesto-v-sovremennom-data-stack\/",
            "title": "StarRocks: Архитектура, Практика и место в современном Data Stack",
            "content_html": "<p><b>StarRocks<\/b> — это аналитическая MPP-база данных нового поколения.<br \/>\nЕсли коротко, она пытается решить трилемму аналитики: объединить скорость <b>ClickHouse<\/b> (за счет векторизации и C++), гибкость <b>Trino<\/b> (поддержка сложных JOIN-ов) и простоту использования <b>MySQL<\/b> (совместимый протокол).<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/logo_starr.svg\" width=\"54\" height=\"62\" alt=\"\" \/>\n<\/div>\n<p>Это короткое руководство проведет вас от понимания архитектуры до построения простого конвейера загрузки данных (ETL) в домашнем продакшене.<\/p>\n<hr \/>\n<h3>Часть 1. Архитектура: FE и BE<\/h3>\n<p>В отличие от PostgreSQL (монолит) или ClickHouse (где узлы часто одноранговые), StarRocks имеет четкое разделение ролей. Это критически важно для понимания масштабирования и эксплуатации.<\/p>\n<h4>1. FE (Frontend) — “Мозг”<\/h4>\n<p>Написан на Java.<\/p>\n<ul>\n<li><b>Роль:<\/b> Управляющий слой.<\/li>\n<li><b>Функции:<\/b>\n<ul>\n  <li>Принимает подключения клиентов (по протоколу MySQL).<\/li>\n  <li>Хранит метаданные (схемы таблиц, права доступа).<\/li>\n  <li>Парсит SQL и строит план выполнения запроса (Query Plan).<\/li>\n  <li>Управляет транзакциями загрузки данных.<\/li>\n<\/ul>\n<\/li>\n<li><b>Масштабирование:<\/b> Обычно запускают 1 или 3 узла для обеспечения высокой доступности (HA).<\/li>\n<li><b>Важно:<\/b> Клиенты (DBeaver, BI, сurl) подключаются <b>только<\/b> к FE.<\/li>\n<\/ul>\n<h4>2. BE (Backend) — “Мускулы”<\/h4>\n<p>Написан на C++ (использует SIMD-инструкции процессора).<\/p>\n<ul>\n<li><b>Роль:<\/b> Слой хранения и вычислений.<\/li>\n<li><b>Функции:<\/b>\n<ul>\n  <li>Физически хранит данные (в колоночном формате).<\/li>\n  <li>Выполняет “тяжелую” работу: фильтрацию, агрегацию, JOIN-ы.<\/li>\n  <li>Управляет репликацией данных.<\/li>\n<\/ul>\n<\/li>\n<li><b>Масштабирование:<\/b> Можно добавлять узлы линейно. Чем больше BE, тем быстрее выполняются запросы и тем больше данных можно хранить.<\/li>\n<\/ul>\n<blockquote>\n<p><b>В Docker All-in-One:<\/b> Оба компонента упакованы в один контейнер для удобства, но слушают разные порты:<\/p>\n<ul>\n<li>`9030`: FE (SQL интерфейс, сюда идет DBeaver).<\/li>\n<li>`8030`: FE (HTTP API для загрузки Stream Load, сюда идет curl).<\/li>\n<li>`8040`: BE (HTTP API метрик и логов).<\/li>\n<\/ul>\n<\/blockquote>\n<hr \/>\n<h3>Часть 2. Быстрый старт (Docker Compose)<\/h3>\n<p>Мы поднимем стек StarRocks и MinIO (S3-совместимое хранилище), используя bridge-сеть для связности.<\/p>\n<p><b>Файл `docker-compose.yml`<\/b> (Полностью рабочий пример):<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">version: &quot;3.9&quot;\n\nnetworks:\n  starrocks-stack-network:\n    driver: bridge\n\nservices:\n  starrocks:\n    image: starrocks\/allin1-ubuntu:4.0-latest\n    container_name: starrocks\n    hostname: starrocks.local.com\n    platform: &quot;linux\/amd64&quot;\n    restart: unless-stopped\n    ports:\n      - &quot;9030:9030&quot; # MySQL Protocol (SQL клиенты)\n      - &quot;8030:8030&quot; # FE HTTP (Stream Load)\n      - &quot;8040:8040&quot; # BE HTTP (Logs\/Metrics)\n    environment:\n      - TZ=UTC\n    networks:\n      starrocks-stack-network:\n    volumes:\n      # Персистентность данных (чтобы данные не исчезли после рестарта)\n      - ${HOME}\/dv\/starrocks\/be\/storage:\/data\/deploy\/starrocks\/be\/storage\n      - ${HOME}\/dv\/starrocks\/be\/log:\/data\/deploy\/starrocks\/be\/log\n      - ${HOME}\/dv\/starrocks\/fe\/meta:\/data\/deploy\/starrocks\/fe\/meta\n      - ${HOME}\/dv\/starrocks\/fe\/log:\/data\/deploy\/starrocks\/fe\/log\n\n  minio:\n    image: quay.io\/minio\/minio\n    container_name: minio\n    platform: &quot;linux\/amd64&quot;\n    hostname: minio.local.com\n    restart: unless-stopped\n    ports:\n      - &quot;9000:9000&quot; # S3 API\n      - &quot;9001:9001&quot; # Web UI\n    networks:\n      starrocks-stack-network:\n    environment:\n      MINIO_ROOT_USER: root\n      MINIO_ROOT_PASSWORD: rootroot\n    volumes:\n      - ${HOME}\/dv\/minio\/data:\/data\n    command: server \/data --console-address &quot;:9001&quot;<\/code><\/pre><p>Запуск:<br \/>\n`docker-compose up -d`<\/p>\n<hr \/>\n<h3>Часть 3. Моделирование данных (Table Design)<\/h3>\n<p>В StarRocks нельзя просто “создать таблицу”. Нужно выбрать тип ключа (<b>Key Model<\/b>), который определит, как база будет хранить и обновлять данные.<\/p>\n<p>Подключение (DBeaver): `localhost:9030`, User: `root`, Password: (пусто).<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE DATABASE IF NOT EXISTS demo_db;\nUSE demo_db;<\/code><\/pre><h4>1. Primary Key Model (Для изменяемых данных)<\/h4>\n<p>Это “флагманская” возможность StarRocks. Она поддерживает быстрые <b>Upsert<\/b> (вставка новых или обновление старых записей по ID) в реальном времени.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE TABLE IF NOT EXISTS users (\n    user_id INT NOT NULL,\n    username VARCHAR(50),\n    email VARCHAR(100),\n    register_date DATE, \n    city VARCHAR(50)\n)\nPRIMARY KEY (user_id) -- Уникальный ключ\nDISTRIBUTED BY HASH(user_id) -- Распределение данных\nPROPERTIES (\n    &quot;replication_num&quot; = &quot;1&quot; -- Для локального теста ставим 1 реплику\n);<\/code><\/pre><h4>2. Aggregate Key Model (Для витрин данных)<\/h4>\n<p>База автоматически агрегирует данные при вставке. Если вы вставите новую продажу с *существующими* датой и категорией, StarRocks не создаст новую строку, а прибавит суммы к уже существующей строке. Это экономит место и ускоряет `GROUP BY`.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE TABLE IF NOT EXISTS daily_sales (\n    report_date DATE NOT NULL,\n    category VARCHAR(50) NOT NULL,\n    \n    -- Метрики с функцией агрегации:\n    total_amount BIGINT SUM DEFAULT &quot;0&quot;, \n    items_sold INT SUM DEFAULT &quot;0&quot;       \n)\nAGGREGATE KEY (report_date, category)\nDISTRIBUTED BY HASH(report_date) BUCKETS 3\nPROPERTIES (\n    &quot;replication_num&quot; = &quot;1&quot;\n);<\/code><\/pre><hr \/>\n<h3>Часть 4. загрузка данных users (Stream Load)<\/h3>\n<p>Для загрузки данных в продакшене мы используем <b>Service Account<\/b> (Техническую учетную запись). Это стандарт безопасности: мы не используем `root` и не используем токены в конфигах (так как они требуют перезагрузки кластера для смены).<\/p>\n<h4>Шаг 1. Создание сервисного пользователя (SQL)<\/h4>\n<p>Выполнять под `root`:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">-- 1. Создаем пользователя-бота\nCREATE USER IF NOT EXISTS 'etl_loader'@'%' IDENTIFIED BY 'SecretPass123!';\n\n-- 2. Даем права ТОЛЬКО на вставку и чтение в базе demo_db\nGRANT INSERT, SELECT ON demo_db.* TO 'etl_loader'@'%';\n\n-- Права применяются мгновенно.<\/code><\/pre><h4>Шаг 2. Загрузка сложного JSON через CURL<\/h4>\n<p>Stream Load — это самый быстрый способ загрузки (до 100 МБ\/сек на узел). Он поддерживает транзакционность (ACID).<\/p>\n<p><b>Пример файла `users.json`:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{\n  &quot;users&quot;: [\n    {&quot;user_id&quot;: 101, &quot;username&quot;: &quot;alex&quot;, &quot;email&quot;: &quot;a@test.com&quot;, &quot;city&quot;: &quot;NY&quot;},\n    {&quot;user_id&quot;: 102, &quot;username&quot;: &quot;bob&quot;, &quot;email&quot;: &quot;b@test.com&quot;, &quot;city&quot;: &quot;LA&quot;}\n  ]\n}<\/code><\/pre><p><b>Команда загрузки (Terminal):<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">curl --location-trusted \\\n    -u etl_loader:SecretPass123! \\\n    -H &quot;Expect: 100-continue&quot; \\\n    -H &quot;format: json&quot; \\\n    -H &quot;strip_outer_array: true&quot; \\\n    -H &quot;json_root: $.users&quot; \\\n    -H &quot;jsonpaths: [\\&quot;$.user_id\\&quot;, \\&quot;$.username\\&quot;, \\&quot;$.email\\&quot;, \\&quot;$.city\\&quot;]&quot; \\\n    -H &quot;columns: user_id, username, email, city&quot; \\\n    -T &quot;users.json&quot; \\\n    -XPUT http:\/\/localhost:8030\/api\/demo_db\/users\/_stream_load<\/code><\/pre><p>Ответ<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{\n    &quot;TxnId&quot;: 9596,\n    &quot;Label&quot;: &quot;a9a37ab6-3678-4c08-95b7-2fd8b6ae973e&quot;,\n    &quot;Db&quot;: &quot;demo_db&quot;,\n    &quot;Table&quot;: &quot;users&quot;,\n    &quot;Status&quot;: &quot;Success&quot;,\n    &quot;Message&quot;: &quot;OK&quot;,\n    &quot;NumberTotalRows&quot;: 2,\n    &quot;NumberLoadedRows&quot;: 2,\n    &quot;NumberFilteredRows&quot;: 0,\n    &quot;NumberUnselectedRows&quot;: 0,\n    &quot;LoadBytes&quot;: 177,\n    &quot;LoadTimeMs&quot;: 153,\n    &quot;BeginTxnTimeMs&quot;: 2,\n    &quot;StreamLoadPlanTimeMs&quot;: 2,\n    &quot;ReadDataTimeMs&quot;: 0,\n    &quot;WriteDataTimeMs&quot;: 26,\n    &quot;CommitAndPublishTimeMs&quot;: 121\n}%<\/code><\/pre><h4>Шаг 3. Загрузка в Aggregate Table (Example)<\/h4>\n<p>Давайте “дольем” данные в таблицу продаж. Агрегация произойдет на лету.<br \/>\nФайл sales.json (простой список):<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">[\n    {&quot;dt&quot;: &quot;2023-11-01&quot;, &quot;cat&quot;: &quot;Electronics&quot;, &quot;amt&quot;: 100, &quot;qty&quot;: 1},\n    {&quot;dt&quot;: &quot;2023-11-01&quot;, &quot;cat&quot;: &quot;Electronics&quot;, &quot;amt&quot;: 50,  &quot;qty&quot;: 1}\n]\n\ncurl --location-trusted \\\n    -u etl_loader:SecretPass123! \\\n    -H &quot;format: json&quot; \\\n    -H &quot;Expect: 100-continue&quot; \\\n    -H &quot;strip_outer_array: true&quot; \\\n    -H &quot;jsonpaths: [\\&quot;$.dt\\&quot;, \\&quot;$.cat\\&quot;, \\&quot;$.amt\\&quot;, \\&quot;$.qty\\&quot;]&quot; \\\n    -H &quot;columns: report_date, category, total_amount, items_sold&quot; \\\n    -T &quot;sales.json&quot; \\\n    -XPUT http:\/\/localhost:8030\/api\/demo_db\/daily_sales\/_stream_load<\/code><\/pre><p>Ответ:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{\n    &quot;TxnId&quot;: 9613,\n    &quot;Label&quot;: &quot;bce0721a-dc2d-4927-be93-e0979a57873d&quot;,\n    &quot;Db&quot;: &quot;demo_db&quot;,\n    &quot;Table&quot;: &quot;daily_sales&quot;,\n    &quot;Status&quot;: &quot;Success&quot;,\n    &quot;Message&quot;: &quot;OK&quot;,\n    &quot;NumberTotalRows&quot;: 2,\n    &quot;NumberLoadedRows&quot;: 2,\n    &quot;NumberFilteredRows&quot;: 0,\n    &quot;NumberUnselectedRows&quot;: 0,\n    &quot;LoadBytes&quot;: 143,\n    &quot;LoadTimeMs&quot;: 52,\n    &quot;BeginTxnTimeMs&quot;: 3,\n    &quot;StreamLoadPlanTimeMs&quot;: 2,\n    &quot;ReadDataTimeMs&quot;: 0,\n    &quot;WriteDataTimeMs&quot;: 24,\n    &quot;CommitAndPublishTimeMs&quot;: 20\n}%<\/code><\/pre><p><b>Разбор заголовков:<\/b><\/p>\n<ul>\n<li>`-u ...`: Авторизация сервисным пользователем.<\/li>\n<li>`Expect: 100-continue`: Критически важно для надежности передачи больших файлов.<\/li>\n<li>`json_root: $.users`: Указывает базе, что данные лежат внутри ключа `users`.<\/li>\n<li>`strip_outer_array: true`: Говорит базе, что внутри лежит массив `[...]` и его нужно “развернуть” в отдельные строки.<\/li>\n<\/ul>\n<hr \/>\n<h3>Часть 5. Совместимость и Trino Dialect<\/h3>\n<p>Одна из сильных сторон StarRocks — способность “притворяться” другими базами данных для облегчения миграции.<\/p>\n<p>Если у вас есть дашборды, написанные на диалекте <b>Trino (Presto)<\/b>, вам не нужно переписывать все SQL-запросы.<\/p>\n<p><b>Пример трансляции функций:<\/b><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">-- Функция Trino, которой нет в StarRocks\nSELECT doy(date '2022-03-06'); \n-- Ошибка: No matching function...\n\n-- Проверяем, как StarRocks переведет этот запрос\nTRANSLATE TRINO select doy(date '2022-03-06');\n-- Результат: SELECT dayofyear('2022-03-06')\n\n-- Включаем режим автоматической трансляции в сессии\nSET sql_dialect = 'trino'; \n\n-- Теперь запрос выполняется корректно, но это не правда. а вот так SELECT dayofyear('2022-03-06') работает. Может бага или у меня версия не та. \nSELECT doy(date '2022-03-06');   \n\n-- Возвращаем нативный режим\nSET sql_dialect = 'starrocks';<\/code><\/pre><p>*(Примечание: Поддержка диалекта постоянно расширяется, но некоторые специфические функции могут требовать ручной замены).*<\/p>\n<hr \/>\n<h3>Итог: Сравнение и Выбор решения ( грубо )<\/h3>\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\"><b>StarRocks<\/b><\/td>\n<td style=\"text-align: center\"><b>ClickHouse<\/b><\/td>\n<td style=\"text-align: center\"><b>Trino (Presto)<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Основной сценарий<\/b><\/td>\n<td style=\"text-align: center\">OLAP-витрины с JOIN-ами и обновлениями данных<\/td>\n<td style=\"text-align: center\">Сбор логов, событий, метрик (Append-only)<\/td>\n<td style=\"text-align: center\">Федерация данных (запрос к S3 + Postgres + Kafka одновременно)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>JOIN производительность<\/b><\/td>\n<td style=\"text-align: center\">⭐⭐⭐ (Excellent, CBO оптимизатор)<\/td>\n<td style=\"text-align: center\">⭐ (Слабо, требует денормализации)<\/td>\n<td style=\"text-align: center\">⭐⭐⭐ (Excellent)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Обновление (UPDATE)<\/b><\/td>\n<td style=\"text-align: center\">⭐⭐⭐ (Работает как в OLTP, Primary Key)<\/td>\n<td style=\"text-align: center\">⭐ (Тяжелые асинхронные ALTER)<\/td>\n<td style=\"text-align: center\">❌ (Обычно только полная перезапись партиций), iceberg не в счёт :)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Язык Engine<\/b><\/td>\n<td style=\"text-align: center\">C++ (SIMD Vectorized)<\/td>\n<td style=\"text-align: center\">C++ (SIMD Vectorized)<\/td>\n<td style=\"text-align: center\">Java (JVM)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Место в стеке<\/b><\/td>\n<td style=\"text-align: center\"><b>Serving Layer<\/b> (Быстрый доступ для BI)<\/td>\n<td style=\"text-align: center\"><b>Storage Layer<\/b> (Хранение логов)<\/td>\n<td style=\"text-align: center\"><b>Query Engine<\/b> (Ad-hoc запросы к Data Lake)<\/td>\n<\/tr>\n<\/table>\n<p><b>Выбирайте StarRocks, если:<\/b><\/p>\n<ol start=\"1\">\n<li>Вам нужна “витрина” для BI (Superset\/Tableau), где данные должны быть всегда свежими (Real-time updates).<\/li>\n<li>Ваш бизнес требует сложных аналитических запросов с множеством JOIN-ов, и ClickHouse не справляется\/падает по памяти.<\/li>\n<li>Вы хотите использовать стандартный протокол MySQL без установки проприетарных драйверов.<\/li>\n<\/ol>\n",
            "date_published": "2026-03-15T19:06:01+03:00",
            "date_modified": "2026-03-15T19:05:56+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer",
                "SQL"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/logo_starr.svg",
            "_date_published_rfc2822": "Sun, 15 Mar 2026 19:06:01 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "323",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/logo_starr.svg"
                ]
            }
        },
        {
            "id": "321",
            "url": "https:\/\/gavrilov.info\/all\/deystvitelno-li-dannye-gotovy-k-ii\/",
            "title": "Действительно ли данные готовы к ИИ",
            "content_html": "<p><b>Автор: Джейкоб Мэтсон<\/b><\/p>\n<p><a href=\"https:\/\/motherduck.com\/blog\/bird-bench-and-data-models\">https:\/\/motherduck.com\/blog\/bird-bench-and-data-models<\/a><\/p>\n<p>Несколько месяцев назад я писал о том, почему нам может <a href=\"https:\/\/motherduck.com\/blog\/who-needs-a-semantic-layer-anyway\">не понадобиться семантический слой<\/a>. Аргумент заключался в том, что ИИ может обнаруживать бизнес-логику из истории запросов, вместо того чтобы заставлять людей заранее определять каждую метрику. Я верил в это. Но у меня не было данных, чтобы это доказать.<\/p>\n<p>Теперь они у меня есть.<\/p>\n<p>Все началось с вопроса одного из наших инвесторов: *“Как различные модели справляются с BIRD при использовании MotherDuck MCP?”* Поэтому я провел эксперимент. Три передовые LLM модели (`Claude Opus 4.5`, `GPT-5.2` и `Gemini 3 Flash`), каждая из которых подключена к базе данных через сервер `MotherDuck MCP`, были запущены на наборе данных `BIRD Mini-Dev`.<\/p>\n<blockquote>\n<p><b>Пояснение:<\/b><\/p>\n<ul>\n<li>MCP (Model Context Protocol):** Стандарт, позволяющий ИИ-моделям безопасно и стандартизировано подключаться к внешним источникам данных и инструментам.<\/li>\n<li>BIRD (BIg Bench for Large-scale Database Grounded Text-to-SQL):** Популярный и сложный бенчмарк (набор тестов) для оценки того, насколько хорошо нейросети умеют переводить естественный язык в SQL-запросы.<\/li>\n<li>Mini-Dev:** Это официальная выборка из 500 вопросов для разработки из бенчмарка BIRD. Она охватывает 11 баз данных в сферах финансов, спорта, образования и здравоохранения.<\/li>\n<\/ul>\n<\/blockquote>\n<p>Модели данных здесь простые. В среднем 7 таблиц на базу данных. Ни в одной нет больше 13 таблиц. Объединения (joins) в основном «один-ко-многим», максимальная глубина — два или три перехода, ноль отношений «многие-ко-многим». Это тот тип схемы, который можно понять за пять минут, прочитав `DDL`.<\/p>\n<blockquote>\n<p><b>Пояснение:<\/b> `DDL` (Data Definition Language) — это часть SQL, используемая для описания структуры базы данных (создание таблиц, колонок, связей).<\/p>\n<\/blockquote>\n<p>Результат? <b>95% точности.<\/b> Никакого семантического слоя. Никакой истории запросов. Никакого специального контекста. Только схема базы данных.<\/p>\n<p>Но это число требует «звездочки» (примечания), и, честно говоря, эта звездочка — самая интересная часть.<\/p>\n<h3>Что на самом деле означают 95%<\/h3>\n<p>Вот что я измерял на самом деле.<\/p>\n<p>Бенчмарк BIRD оценивает точность, используя <b>Execution Accuracy (EX)<\/b>: запускается предсказанный SQL и «золотой» (эталонный) SQL, сравниваются наборы результатов, и ставится бинарная оценка «сдал\/не сдал». При этих строгих правилах текущий уровень развития технологий (SOTA) составляет около 76. Мои модели набрали 64 на тренировочной выборке и 58 на тестовой.<\/p>\n<p>Звучит плохо. Но у строгой оценки BIRD есть хорошо задокументированная проблема. В статье 2025 года, представляющей метрику `FLEX`, было обнаружено, что точность выполнения (execution accuracy) BIRD совпадает с оценками экспертов-людей только в 62% случаев. Почти 4 из 10 суждений ошибочны, в основном это ложноотрицательные результаты, когда бенчмарк отвергает ответы, которые люди бы приняли.<\/p>\n<p>Эти 62 бросились мне в глаза, потому что они почти точно совпадают с моей смешанной точностью при строгой оценке в 60.5 (64 обучение \/ 58 тест). То же наблюдение, но с другой стороны. Метрика `FLEX` пришла к этому с помощью проверяющих людей. Я пришел к этому, ослабив условия тестирования.<\/p>\n<p>Подумайте, что это значит для таблицы лидеров. Если бенчмарк согласен с людьми только в 62 случаев, то чтобы набрать выше 62 по строгим правилам, вы должны начать воспроизводить ошибки бенчмарка. Вы перестаете учиться писать правильный SQL. Вы начинаете учиться соответствовать специфической, иногда ошибочной интерпретации каждого вопроса в BIRD. Системы с рейтингом 76 закрепили эти ошибки суждения в своем обучении. Они получают более высокие баллы, становясь *хуже* в выполнении реальной задачи.<\/p>\n<p>Поэтому я построил более реалистичную оценку. Я разделил 500 вопросов на тренировочный набор (151 вопрос) и тестовый набор (349 вопросов).<\/p>\n<p>Я использовал <b>тренировочный набор (train)<\/b> для калибровки оценки: вручную пересматривал ошибки, создавал исправленные «платиновые» ответы там, где «золотой» SQL BIRD был ошибочным, и настраивал правила частичного совпадения. <b>Тестовый набор (test)<\/b> был контрольным.<\/p>\n<p>Вот как выглядит точность, если смягчать критерии оценки уровень за уровнем:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Уровень оценки (Scoring Tier)<\/td>\n<td style=\"text-align: center\">Train<\/td>\n<td style=\"text-align: center\">Test<\/td>\n<td style=\"text-align: center\">Что добавляется<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Только совпадение с Gold<\/b> (≈ офиц. BIRD)<\/td>\n<td style=\"text-align: center\">64.0<\/td>\n<td style=\"text-align: center\">58.2<\/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\">73.1<\/td>\n<td style=\"text-align: center\">58.5<\/td>\n<td style=\"text-align: center\">Исправляет известные ошибки в «золотом» SQL BIRD (см. примечание ниже)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>+ Допуск форматирования<\/b><\/td>\n<td style=\"text-align: center\">78.8<\/td>\n<td style=\"text-align: center\">65.5<\/td>\n<td style=\"text-align: center\">Различия в `DISTINCT`, лишние колонки, округление<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>+ Судья LLM<\/b><\/td>\n<td style=\"text-align: center\">94.9<\/td>\n<td style=\"text-align: center\">94.4<\/td>\n<td style=\"text-align: center\">“Принял бы человек этот ответ?”<\/td>\n<\/tr>\n<\/table>\n<blockquote>\n<p><b>Примечание:<\/b> «Платиновые» исправления существуют только для тренировочного набора, так как я вручную проверил эти 151 вопрос. Вот почему уровень «Платина» почти не меняется на тесте +0.3 pp против +9.1 pp на тренировке). Но посмотрите на уровень с судьей: 94.9 на тренировке и 94.4 на тесте. Разница всего в половину процентного пункта. Оценка держится на контрольной выборке даже без моих исправлений вручную.<\/p>\n<\/blockquote>\n<h4>Результаты тренировочной выборки (151 вопрос, все 3 модели):<\/h4>\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\">STRICT (≈ BIRD EX)<\/td>\n<td style=\"text-align: center\">REALISTIC<\/td>\n<td style=\"text-align: center\">Общая стоимость<\/td>\n<td style=\"text-align: center\">Вызовы инструментов (P5 \/ Median \/ P95)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`Gemini 3 Flash`<\/td>\n<td style=\"text-align: center\">68.2<\/td>\n<td style=\"text-align: center\">94.0<\/td>\n<td style=\"text-align: center\">1.80<\/td>\n<td style=\"text-align: center\">3 \/ 6 \/ 9<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`Claude Opus 4.5`<\/td>\n<td style=\"text-align: center\">64.9<\/td>\n<td style=\"text-align: center\">95.4<\/td>\n<td style=\"text-align: center\">26.37<\/td>\n<td style=\"text-align: center\">4 \/ 6 \/ 9<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`GPT-5.2`<\/td>\n<td style=\"text-align: center\">58.9<\/td>\n<td style=\"text-align: center\">95.4<\/td>\n<td style=\"text-align: center\">6.87<\/td>\n<td style=\"text-align: center\">4 \/ 7 \/ 12<\/td>\n<\/tr>\n<\/table>\n<h4>Результаты тестовой выборки (349 вопросов, 2 модели):<\/h4>\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\">STRICT (≈ BIRD EX)<\/td>\n<td style=\"text-align: center\">REALISTIC<\/td>\n<td style=\"text-align: center\">Общая стоимость<\/td>\n<td style=\"text-align: center\">Вызовы инструментов (P5 \/ Median \/ P95)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`Gemini 3 Flash`<\/td>\n<td style=\"text-align: center\">60.7<\/td>\n<td style=\"text-align: center\">94.6<\/td>\n<td style=\"text-align: center\">3.96<\/td>\n<td style=\"text-align: center\">4 \/ 6 \/ 9<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`GPT-5.2`<\/td>\n<td style=\"text-align: center\">55.6<\/td>\n<td style=\"text-align: center\">94.3<\/td>\n<td style=\"text-align: center\">15.32<\/td>\n<td style=\"text-align: center\">4 \/ 7 \/ 11<\/td>\n<\/tr>\n<\/table>\n<blockquote>\n<p>*Примечание: `Claude Opus` не запускался на тестовом наборе. После того как все три модели сошлись на ~95% на тренировке, тратить еще 60+, чтобы доказать то же самое на 349 вопросах, показалось нецелесообразным.*<\/p>\n<\/blockquote>\n<p>Медианная модель делает 6-7 вызовов инструментов MCP на вопрос при лимите в 10 итераций. Типичный вопрос выглядит так: изучить схему, просмотреть некоторые колонки, набросать запрос, проверить результаты, уточнить, готово. Некоторые модели, такие как `GPT-5.2`, делают несколько вызовов инструментов за итерацию, поэтому его показатель P95, равный 12, превышает лимит итераций.<\/p>\n<p>Все три модели достигают <b>94-95% при реалистичной оценке<\/b>, независимо от того, где они начинают при строгой оценке. На тренировочной выборке разрыв между «лучшим» и «худшим» сокращается с 12.6 процентных пунктов до 1.4. На тесте — с 5.1 до 0.3. Берите любую передовую модель.<\/p>\n<h3>Бенчмарк иногда ошибается<\/h3>\n<p>BIRD — хороший бенчмарк. Но в нем есть баги. Только в тренировочном наборе (151 вопрос) я нашел 49 случаев, где «золотой» SQL явно неверен. Я не проверял вручную тестовый набор, поэтому реальное число для всех 500 вопросов, вероятно, выше.<\/p>\n<p>Вот пример, который мне запомнился. Вопрос просит список школ, чей совокупный балл превышает 1500. «Золотой» SQL проверяет `count` (количество) студентов, набравших более 1500 баллов. Совершенно другой запрос, совершенно другой ответ. Вы читаете вопрос, читаете «правильный» ответ и думаете: подождите, но спрашивали-то не об этом.<\/p>\n<p>Я создал исправленные «платиновые» ответы для этих случаев. В среднем около 14 из 151 вопроса тренировочной выборки для каждой модели совпали с платиновым ответом вместо золотого, добавив 9.1 процентных пунктов.<\/p>\n<h3>Людей не волнует форматирование<\/h3>\n<p>На тренировочной выборке еще +5.7 pp получается за счет принятия результатов, которые верны по существу, но не проходят проверку на строгое равенство:<\/p>\n<ul>\n<li><b>Лишние колонки (30 случаев):<\/b> Модель вернула запрошенные данные плюс дополнительный контекст. Человек сказал бы «спасибо, это полезно». Бенчмарк говорит «провал».<\/li>\n<li><b>Несовпадения `DISTINCT` (41 случай):<\/b> Модель использовала `SELECT DISTINCT`, когда в золотом ответе этого не было, или наоборот. Уникальные значения совпадают идеально. Человек бы даже не заметил.<\/li>\n<li><b>Различия в округлении (3 случая):<\/b> Золотой ответ 24.67, ответ модели 24.6667. То же число, разная точность.<\/li>\n<\/ul>\n<p>Ни один из этих ответов не является неверным. Это различия в форматировании, которые важны только для функции сравнения строк.<\/p>\n<h3>Человек (LLM)-в-петле (The LLM-in-the-Loop)<\/h3>\n<p>Оставшийся разрыв (16 pp на тренировке, 29 pp на тесте) закрывается <b>судьей LLM<\/b>. Я использовал `Gemini 3 Flash` для проверки каждого «проваленного» ответа с вопросом: *действительно ли этот SQL отвечает на вопрос?*<\/p>\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> (Missing rows)<\/td>\n<td style=\"text-align: center\">57<\/td>\n<td style=\"text-align: center\">Модель отфильтровала строже, чем золотой стандарт, но это обоснованно.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Лишние строки<\/b> (Extra rows)<\/td>\n<td style=\"text-align: center\">33<\/td>\n<td style=\"text-align: center\">Модель интерпретировала вопрос более широко.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Близкие значения<\/b> (Values close)<\/td>\n<td style=\"text-align: center\">19<\/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\">14<\/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\">11<\/td>\n<td style=\"text-align: center\">Возвращено меньше колонок, но ответ на вопрос дан.<\/td>\n<\/tr>\n<\/table>\n<p>Это оценочные суждения. Должен ли запрос «перечислите все школы в районе» включать чартерные школы? Разумные люди могут не согласиться. Строгий бенчмарк выбирает одну интерпретацию и наказывает за все остальные. Судья просто спрашивает, можно ли обосновать интерпретацию модели.<\/p>\n<p>Если вы создаете ИИ-аналитику, это важно. Никто не выпускает продукт text-to-SQL, где пользователь видит сырые результаты без этапа проверки. Всегда есть человек или LLM, проверяющий выходные данные. Эти 94-95% отражают то, как эти продукты работают на самом деле. 58-64% отражают то, как работают бенчмарки.<\/p>\n<h3>А как насчет контекста?<\/h3>\n<p>Вы могли бы ожидать, что дополнительный контекст поможет. Комментарии к колонкам, описания, подсказки о значении данных. Это интуиция, лежащая в основе семантических слоев и механизмов контекста.<\/p>\n<p>Я протестировал это. Те же 500 вопросов, все модели, с комментариями к колонкам каждой таблицы и без них.<\/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\">Train<\/td>\n<td style=\"text-align: center\">Test<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Без комментариев<\/b><\/td>\n<td style=\"text-align: center\">94.9<\/td>\n<td style=\"text-align: center\">94.4<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>С комментариями<\/b><\/td>\n<td style=\"text-align: center\">96.0<\/td>\n<td style=\"text-align: center\">94.6<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Дельта<\/b><\/td>\n<td style=\"text-align: center\">1.1 pp<\/td>\n<td style=\"text-align: center\">0.2 pp<\/td>\n<\/tr>\n<\/table>\n<p>Один процентный пункт на тренировке, почти ничего на тесте. В большинстве вопросов правильность не изменилась.<\/p>\n<p>Если разбить по базам данных, становится интересно. Чем сложнее схема, тем больше помогают комментарии (усредненно по train и test):<\/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\">`debit_card_specializing`<\/td>\n<td style=\"text-align: center\">85.5 (самая сложная)<\/td>\n<td style=\"text-align: center\">8.7 pp<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`european_football_2`<\/td>\n<td style=\"text-align: center\">93.2<\/td>\n<td style=\"text-align: center\">3.4 pp<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">`california_schools`<\/td>\n<td style=\"text-align: center\">95.7 (самая легкая)<\/td>\n<td style=\"text-align: center\">2.9 pp<\/td>\n<\/tr>\n<\/table>\n<p>Комментарии помогают, когда схема действительно запутанная. Таблица `debit_card_specializing` (попробуйте угадать, как выглядит эта схема) получила самый большой прирост. Но схемы с интуитивными названиями и очевидными связями? Там комментарии сделали только хуже. У моделей уже сформировалась правильная ментальная модель, а комментарии внесли шум.<\/p>\n<p>Каждый разработчик знает это о комментариях в коде. Полезны при реальной неоднозначности. Вредны, когда констатируют очевидное. `\/\/ увеличить i на 1` еще никому не помогло.<\/p>\n<h3>Почему простые модели данных работают<\/h3>\n<p>Базы данных BIRD — это не корпоративные хранилища данных. Они простые:<\/p>\n<ul>\n<li>7 таблиц в среднем.<\/li>\n<li>9 внешних ключей в среднем, в основном «один-ко-многим».<\/li>\n<li>Ноль связей «многие-ко-многим».<\/li>\n<li>Глубина join макс. 2-3 перехода, нет глубоких иерархий.<\/li>\n<\/ul>\n<p>LLM читают эти схемы так же, как опытный аналитик читает DDL. Они видят таблицу `schools` с колонками `school_name`, `district` и `enrollment`, и они знают, что делать. Внешний ключ от `schools` к `scores`? Они знают, как их соединить (join). Никому не нужен семантический слой, чтобы объяснить, что “enrollment” означает «количество студентов».<\/p>\n<p><b>Хорошее моделирование данных — это и есть семантический слой.<\/b> Когда ваши таблицы названы хорошо, а объединения прямолинейны, у LLM есть всё необходимое.<\/p>\n<h3>Во что я бы инвестировал в первую очередь<\/h3>\n<p>Каждая среда уникальна, но вот как бы я расставил приоритеты, основываясь на том, что увидел:<\/p>\n<ol start=\"1\">\n<li><b>Начните с модели данных.<\/b> Чистые таблицы, понятные названия, простые объединения. Если опытный аналитик может посмотреть на вашу схему и понять ее за несколько минут, то и LLM сможет.<\/li>\n<li><b>Затем добавьте целевой контекст.<\/b> Комментарии к колонкам и метаданные, но только там, где действительно существует путаница. Документируйте таблицы типа `debit_card_specializing`, а не `schools`.<\/li>\n<li><b>История запросов идет следом.<\/b> Она становится важнее по мере усложнения предметной области, особенно для обнаружения недокументированных бизнес-правил (вроде “abnormal GOT > 60”). Базы данных BIRD имеют простые правила. Но я работаю над (проектом) `DABstep`, у которого простая модель данных, но очень сложные правила предметной области. Тот вид знаний, который живет в головах людей, а не в названиях колонок. Там история запросов и подобранный контекст будут значить гораздо больше. Но даже тогда чистая модель данных стоит на первом месте.<\/li>\n<\/ol>\n<p>Наконец, не беспокойтесь о формальном семантическом слое. Если ваша модель данных чиста, а контекст целенаправлен, это почти ничего не добавляет для сценариев использования ИИ. На самом деле, кажется, что это даже мешает, так как ИИ отлично пишет SQL, но менее хорош в работе с другими инструментами.<\/p>\n<h3>Начните сейчас<\/h3>\n<p>Планка для «данных, готовых к ИИ», ниже, чем вам говорит индустрия.<\/p>\n<p>Вам не нужен “движок контекста”, семантический слой, годы истории запросов или специализированная платформа метаданных. Вам нужна <b>чистая модель данных и LLM<\/b>. Найдите домен, который готов к этому, и начните там.<\/p>\n<p>Разрыв между «точностью бенчмарка» и «примет ли это человек?» составил 31 pp на тренировочной выборке и 36 pp на тестовой. Это огромный разрыв, и он закрывается в тот момент, когда вы включаете человека или LLM в цикл проверки. Именно так и работает любой продукт ИИ-аналитики.<\/p>\n<p>Если ваша модель данных чиста, начните сегодня. Направьте LLM на вашу схему и задавайте вопросы. Если ваша модель данных не чиста, теперь вы знаете, с чего начать.<\/p>\n<p>***<\/p>\n<h4>Итоги статьи<\/h4>\n<ol start=\"1\">\n<li><b>Проблема:<\/b> Принято считать, что для работы ИИ с базами данных (Text-to-SQL) нужны сложные семантические слои, история запросов и контекст.<\/li>\n<li><b>Эксперимент:<\/b> Автор протестировал работу современных LLM (Claude, Gemini, GPT) на известном наборе данных BIRD.<\/li>\n<li><b>Открытие 1:<\/b> Формальные бенчмарки занижают качество работы ИИ. Они требуют строгого совпадения SQL-запросов, хотя люди принимают ответы с правильными данными, но другим форматированием (лишние колонки, другой порядок сортировки). Истинная (“реалистичная”) точность моделей достигает <b>95%<\/b>, тогда как бенчмарк показывает около 60%.<\/li>\n<li><b>Открытие 2:<\/b> “Готовность данных к ИИ” сводится к понятной структуре базы данных. Чистые таблицы, внятные названия колонок и простые связи работают лучше, чем нагромождение комментариев.<\/li>\n<li><b>Открытие 3:<\/b> Дополнительные комментарии (контекст) нужны только для реально запутанных схем. В простых случаях они даже мешают, создавая шум.<\/li>\n<li><b>Вывод:<\/b> Не тратьте ресурсы на сложные семантические надстройки. Инвестируйте в <b>чистоту модели данных<\/b> (понятные имена таблиц и полей). Хорошая модель данных — это и есть лучший семантический слой для ИИ.<\/li>\n<\/ol>\n",
            "date_published": "2026-03-14T00:19:28+03:00",
            "date_modified": "2026-03-14T00:19:21+03:00",
            "tags": [
                "AI",
                "big data",
                "Data",
                "MCP"
            ],
            "_date_published_rfc2822": "Sat, 14 Mar 2026 00:19:28 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "321",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "320",
            "url": "https:\/\/gavrilov.info\/all\/bitva-titanov-analitiki-realnogo-vremeni-starrocks-protiv-clickh\/",
            "title": "Битва титанов аналитики реального времени: StarRocks против ClickHouse",
            "content_html": "<p>В мире больших данных, где счет идет на петабайты, а задержка измеряется миллисекундами, выбор правильного аналитического движка определяет успех продукта. Сегодня мы разберем восходящую звезду StarRocks и классического гиганта ClickHouse, а также посмотрим, как Netflix удалось укротить свои логи на экстремальных скоростях.<\/p>\n<h3>Часть 1: Обзор технологий и кейс Netflix<\/h3>\n<h4>StarRocks: Субсекундная аналитика нового поколения<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image.png-1.jpg\" width=\"2560\" height=\"1078\" alt=\"\" \/>\n<\/div>\n<p><b>StarRocks<\/b> — это высокопроизводительный аналитический движок (MPP database) нового поколения, разработанный для сценариев, где скорость имеет решающее значение. Будучи проектом Linux Foundation, он позиционирует себя как самый быстрый открытый движок запросов для субсекундной аналитики как внутри собственного хранилища, так и поверх архитектуры Data Lakehouse.<\/p>\n<p><b>Ключевые особенности StarRocks:<\/b><\/p>\n<ul>\n<li>Универсальность:** Поддерживает почти любые сценарии — от многомерной OLAP-аналитики и realtime-дэшбордов до ad-hoc запросов аналитиков.<\/li>\n<li>Скорость:** Использует векторизованный движок исполнения, CBO (Cost-Based Optimizer) и пайплайновый параллелизм, что позволяет обгонять конкурентов на сложных запросах с JOIN-ами.<\/li>\n<li>Архитектура:** Native cloud-ready, легко масштабируется горизонтально. Умеет работать “on and off the lakehouse” — то есть быстро читать данные напрямую из S3\/HDFS (форматы Parquet, ORC, Iceberg, Hudi) без необходимости их обязательной загрузки внутрь базы.<\/li>\n<\/ul>\n<hr \/>\n<h4>Кейс Netflix: Как оптимизировать логирование петабайтного масштаба с ClickHouse<\/h4>\n<p>*( адаптация материала из блога ClickHouse)* <a href=\"https:\/\/clickhouse.com\/blog\/netflix-petabyte-scale-logging\">https:\/\/clickhouse.com\/blog\/netflix-petabyte-scale-logging<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Screenshot-from-2026-03-06-01-15-33.png\" width=\"833\" height=\"380\" alt=\"\" \/>\n<\/div>\n<p>В Netflix масштаб диктует всё. Инженер Дэниел Муино поделился инсайтами о том, как их система логирования справляется с <b>5 петабайтами логов ежедневно<\/b>, обрабатывая в среднем 10.6 миллионов событий в секунду и отвечая на запросы быстрее, чем за секунду.<\/p>\n<p>Для достижения такой производительности потребовалось не просто выбрать правильную базу данных (ClickHouse), но и внедрить три критических инженерных оптимизации.<\/p>\n<h5>Архитектура: Горячее и холодное<\/h5>\n<p>Netflix использует гибридный подход:<\/p>\n<ul>\n<li>Горячий слой (ClickHouse):** Хранит недавние логи, где критична скорость для интерактивной отладки. Данные поступают через Kafka\/Kinesis в ClickHouse практически мгновенно.<\/li>\n<li>Холодный слой (Apache Iceberg):** Обеспечивает экономичное долговременное хранение исторических данных на S3.<\/li>\n<li>Единый API автоматически решает, к какому слою обращаться, скрывая сложность от инженеров.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image.png.jpg\" width=\"2560\" height=\"1403\" alt=\"\" \/>\n<\/div>\n<p>Результат: логи доступны для поиска через 20 секунд после генерации (при SLA в 5 минут), а сложные аналитические запросы выполняются почти мгновенно.<\/p>\n<h5>Три главные оптимизации<\/h5>\n<p><b>1. Ingestion: Свой лексер вместо Regex<\/b><br \/>\nИзначально Netflix использовал регулярные выражения для группировки похожих логов (fingerprinting). На скорости 10 млн событий\/сек это стало узким местом.<\/p>\n<ul>\n<li>Решение:* Команда переписала логику, создав <b>сгенерированный лексер<\/b> с помощью JFlex.<\/li>\n<li>Результат:* Рост пропускной способности в 8-10 раз. Время обработки одного события упало с 216 до 23 микросекунд.<\/li>\n<\/ul>\n<p><b>2. Сериализация: Отказ от JDBC<\/b><br \/>\nСтандартные JDBC-вставки через Java-клиент создавали оверхед на согласование схем. Переход на низкоуровневый формат `RowBinary` помог, но потребление CPU оставалось высоким.<\/p>\n<ul>\n<li>Решение:* Дэниел реверс-инжинирил протокол Go-клиента ClickHouse (который поддерживает нативный формат) и написал <b>собственный энкодер<\/b>. Он генерирует LZ4-сжатые блоки в нативном протоколе ClickHouse.<\/li>\n<li>Результат:* Снижение нагрузки на CPU и памяти при той же пропускной способности.<\/li>\n<\/ul>\n<p><b>3. Запросы: Шардирование карт тегов (Tag Maps)<\/b><br \/>\nИнженеры Netflix активно используют кастомные теги (фильтры по microservice_id, request_id). Изначально они хранились как `Map(String, String)`. В ClickHouse это реализовано как два параллельных массива, что требует линейного сканирования при поиске. При 25 000 уникальных ключей в час запросы тормозили.<\/p>\n<ul>\n<li>Решение:* Шардирование карты. Ключи тегов хешируются в 31 меньшую карту. Запрос сразу “прыгает” в нужный шард вместо перебора всех ключей.<\/li>\n<li>Результат:* Время фильтрующих запросов упало с 3 секунд до 1.3, а сложных проекций — с 3 секунд до <b>700 мс<\/b>.<\/li>\n<\/ul>\n<hr \/>\n<h3>Часть 2: ClickHouse vs StarRocks — Битва за Lakehouse<\/h3>\n<p>Обе системы являются лидерами в мире OLAP (On-Line Analytical Processing), используют MPP-архитектуру и колоночное хранение. Однако их философия и степень готовности к современной концепции <b>Lakehouse<\/b> (аналитика данных непосредственно в озере данных без копирования) различаются.<\/p>\n<h4>1. Архитектурные корни и специализация<\/h4>\n<ul>\n<li>ClickHouse:**\n<ul>\n  <li>ДНК:* Изначально создавался для Яндекс.Метрики. Король <b>единой широкой таблицы<\/b>.<\/li>\n  <li>Сильная сторона:* Непревзойденная скорость записи и чтения на одной таблице. Идеален для логов (как у Netflix), телеметрии, событийных данных.<\/li>\n  <li>Слабая сторона:* JOIN-ы (соединения таблиц). ClickHouse умеет их делать, но исторически это не его конек. Оптимизатор запросов долгое время был рудиментарным, требуя от пользователя ручной оптимизации порядка таблиц.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>StarRocks:**\n<ul>\n  <li>ДНК:* Эволюционировал из Apache Doris. Создавался с прицелом на сложные сценарии аналитики.<\/li>\n  <li>Сильная сторона:* <b>CBO (Cost-Based Optimizer)<\/b> уровня Oracle или Teradata. StarRocks блестяще справляется со сложными SQL-запросами, включая многотабличные JOIN-ы “звезда” и “снежинка”.<\/li>\n  <li>Специфика:* Ориентирован на обновление данных в реальном времени (Primary Key table engine) и векторизованную обработку сложных вычислений.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>2. Степень готовности к Lakehouse (Работа с S3, HDFS, Iceberg)<\/h4>\n<p>Здесь наблюдается главное стратегическое расхождение.<\/p>\n<p><b>StarRocks: Native Lakehouse Engine<\/b><br \/>\nStarRocks позиционирует себя как движок, который может вообще <b>не хранить данные у себя<\/b>, а выступать только быстрым вычислительным слоем поверх S3\/MinIO.<\/p>\n<ul>\n<li>Кэширование:** Имеет продвинутый локальный кэш данных (Local Data Cache), который подтягивает горячие данные из S3 на диски воркеров, обеспечивая скорость, сравнимую с нативным хранением.<\/li>\n<li>Каталоги:** Бесшовная интеграция с Hive Metastore, AWS Glue, Iceberg, Hudi, Delta Lake. Вы просто подключаете каталог и пишете `SELECT` к таблицам в S3 без `CREATE TABLE`.<\/li>\n<li>Вердикт:<b> StarRocks **полностью готов<\/b> к Lakehouse. Это один из лучших выборов для сценария “данные лежат в S3 в формате Parquet\/Iceberg, а нам нужен быстрый SQL поверх них”.<\/li>\n<\/ul>\n<p><b>ClickHouse: Storage First, Lakehouse Second<\/b><br \/>\nClickHouse исторически — это система хранения. Хотя поддержка S3 и Data Lakes активно развивается (особенно в 2024-2025 годах), подход отличается.<\/p>\n<ul>\n<li>Интеграция:** ClickHouse может читать из S3 (`s3()` table function или S3 table engine). Поддерживает Iceberg и Hudi.<\/li>\n<li>Производительность:** Чтение “холодных” данных из S3 в ClickHouse часто медленнее, чем в StarRocks, из-за особенностей реализации сканирования и работы с метаданными внешних форматов.<\/li>\n<li>Кейс Netflix подтверждает:<b> Netflix использует ClickHouse **как горячее хранилище<\/b>, копируя туда данные. А для лекхоуса (Iceberg) они используют отдельные движки (вероятно, Trino или Spark), а ClickHouse выступает именно как акселератор для свежих данных.<\/li>\n<li>Вердикт:<b> ClickHouse движется в сторону Lakehouse (разделение Storage и Compute, S3-backed MergeTree), но его главная суперсила по-прежнему раскрывается, когда данные **импортированы<\/b> в его родной формат.<\/li>\n<\/ul>\n<h4>Пример использования ClickHouse (из статьи выше)<\/h4>\n<p>В примере Netflix мы видим классический паттерн использования ClickHouse, где он силен максимально:<\/p>\n<blockquote>\n<p>*“ClickHouse находится в сердце системы как горячий слой (hot tier). Он хранит недавние логи, где скорость критична... Для исторических данных Netflix использует Apache Iceberg.”*<\/p>\n<\/blockquote>\n<p>Это подтверждает тезис: ClickHouse идеален, когда вы загружаете данные в него (Ingest heavy). StarRocks же часто выигрывает там, где данные уже лежат в озере, и вы не хотите их никуда копировать, либо, когда вам нужны сложные JOIN-ы поверх этих данных.<\/p>\n<hr \/>\n<h4>Итог и рекомендации<\/h4>\n<p>Выбор между StarRocks и ClickHouse больше не стоит в плоскости “кто быстрее сканирует одну колонку”. Обе системы феноменально быстры. Вопрос в архитектуре ваших данных.<\/p>\n<p><b>Рекомендации:<\/b><\/p>\n<ol start=\"1\">\n<li><b>Выбирайте ClickHouse, если:<\/b>\n<ul>\n  <li>Ваша главная задача — работа с логами, метриками, clickstream (как у Netflix).<\/li>\n  <li>У вас плоская структура данных (одна широкая таблица), и JOIN-ы редки.<\/li>\n  <li>Вам нужна максимальная скорость вставки (ingestion) и максимальное сжатие данных на диске.<\/li>\n  <li>У вас есть ресурсы на инженерию: ClickHouse гибок, но, как показал кейс Netflix, требует “прямых рук” для тонкой настройки (кастомные кодеки, шардирование тегов).<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Выбирайте StarRocks, если:<\/b>\n<ul>\n  <li>Вы строите <b>Data Lakehouse<\/b>: данные лежат в S3 (Iceberg\/Parquet), и вы хотите анализировать их без ETL\/копирования.<\/li>\n  <li>У вас сложная модель данных (схема “Звезда” или “Снежинка”) и много JOIN-ов в запросах.<\/li>\n  <li>Вам нужны обновления данных (UPSERT\/DELETE) в реальном времени с использованием Primary Keys.<\/li>\n  <li>Вы хотите упростить поддержку и получить оптимизатор запросов, который многое сделает за вас “из коробки”.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Приложение:<\/p>\n<p>Ниже представлен анализ списка компаний, использующих <b>StarRocks<\/b>. Они разделены по сферам деятельности, а также ранжированы по глубине использования технологии и вкладу в развитие проекта.<\/p>\n<h4>1. Сферы деятельности компаний<\/h4>\n<p>Вот краткое описание того, чем занимается каждая компания из вашего списка:<\/p>\n<p><b>Технологии, Интернет и E-commerce:<\/b><\/p>\n<ul>\n<li>Alibaba:** Крупнейший китайский холдинг электронной коммерции и облачных вычислений.<\/li>\n<li>Shopee:** Ведущая платформа электронной коммерции в Юго-Восточной Азии и Тайване.<\/li>\n<li>Trip.com:** Одно из крупнейших в мире онлайн-турагентств.<\/li>\n<li>Airbnb:** Онлайн-площадка для размещения, поиска и краткосрочной аренды жилья.<\/li>\n<li>Xiaohongshu (RedNote):** Китайская социальная сеть и платформа электронной коммерции (аналог Instagram + Pinterest).<\/li>\n<li>Zepto:** Сервис быстрой доставки продуктов (quick commerce) из Индии.<\/li>\n<li>Naver:** Ведущая южнокорейская интернет-компания (поисковик, карты и др.).<\/li>\n<\/ul>\n<p><b>Социальные сети и Медиа:<\/b><\/p>\n<ul>\n<li>Pinterest:** Фотохостинг, социальная сеть для обмена идеями.<\/li>\n<li>Tencent (Games & LLM):** Технологический гигант, владелец WeChat, крупнейший в мире издатель видеоигр.<\/li>\n<li>iQiyi:** Крупная китайская платформа онлайн-видео (аналог Netflix).<\/li>\n<li>SmartNews:** Агрегатор новостей (популярен в Японии и США).<\/li>\n<\/ul>\n<p><b>Финтех и Криптовалюты:<\/b><\/p>\n<ul>\n<li>Coinbase:** Крупнейшая американская криптовалютная биржа.<\/li>\n<li>Intuit:** Американская компания, разработчик финансового ПО (QuickBooks, TurboTax).<\/li>\n<li>TRM Labs:** Блокчейн-аналитика, порядочность в криптосфере и compliance.<\/li>\n<li>Yuno:** Финтех-оркестратор платежей.<\/li>\n<\/ul>\n<p><b>B2B SaaS и Корпоративное ПО:<\/b><\/p>\n<ul>\n<li>Airtable:** Облачный сервис для работы с базами данных и таблицами (no-code).<\/li>\n<li>Celonis:** Лидер в области Process Mining (анализ бизнес-процессов).<\/li>\n<li>Cisco:** Мировой лидер в области сетевых технологий и кибербезопасности.<\/li>\n<li>Demandbase:** Платформа для ABM-маркетинга (Account-Based Marketing).<\/li>\n<li>Eightfold.ai:** Платформа для управления талантами на базе ИИ.<\/li>\n<li>Freshа:** Платформа для бронирования услуг в сфере красоты и здоровья.<\/li>\n<li>SplitMetrics:** Платформа для A\/B тестирования и оптимизации мобильных приложений.<\/li>\n<li>Verisoul:** Платформа для выявления фейковых пользователей и ботов.<\/li>\n<\/ul>\n<p><b>Транспорт и Логистика:<\/b><\/p>\n<ul>\n<li>Didi:** Китайский агрегатор такси (аналог Uber).<\/li>\n<li>Grab:** Супер-приложение из Юго-Восточной Азии (такси, доставка еды, платежи).<\/li>\n<\/ul>\n<p><b>Игры:<\/b><\/p>\n<ul>\n<li>PlaySimple Games:** Разработчик мобильных словесных игр.<\/li>\n<\/ul>\n<p><b>Сельское хозяйство:<\/b><\/p>\n<ul>\n<li>HerdWatch:** ПО для управления фермерскими хозяйствами.<\/li>\n<\/ul>\n<p><b>Энергетика:<\/b><\/p>\n<ul>\n<li>Haezoom:** Южнокорейская платформа в сфере солнечной энергетики (Energy AI).<\/li>\n<\/ul>\n<p><b>Ритейл (Merchandise):<\/b><\/p>\n<ul>\n<li>Fanatics:** Мировой лидер по продаже лицензионной спортивной атрибутики.<\/li>\n<\/ul>\n<hr \/>\n<h4>2. Ранжирование по степени использования (Use Case Depth)<\/h4>\n<p>Это ранжирование основано на публично доступных кейсах (case studies), объемах данных и критичности систем, переведенных на StarRocks.<\/p>\n<p><b>Уровень 1: Heavy Users \/ Mission Critical (Ключевые внедрения)<\/b><\/p>\n<p>Эти компании заменили устаревшие хранилища данных (Snowflake, ClickHouse, Druid) на StarRocks для критически важных задач с огромными объемами данных.<\/p>\n<ol start=\"1\">\n<li><b>Airbnb:<\/b> Используют StarRocks для метрик реального времени и “умного” ценообразования (Minerva). Огромные объемы данных, строгие требования к задержке.<\/li>\n<li><b>Tencent (Games & LLM):<\/b> Один из самых масштабных пользователей. Унифицировали аналитику (заменив Hive\/Spark\/Druid), что позволило анализировать данные сотен игр в реальном времени.<\/li>\n<li><b>Trip.com:<\/b> Полностью отказались от ClickHouse и частично от Hive в пользу StarRocks для ускорения отчетов. Обрабатывают петабайты данных, высокая конкуренция запросов.<\/li>\n<li><b>Shopee:<\/b> Используют StarRocks для Data Service (API), ускорив запросы в 3 раза по сравнению с Presto. Критически важно для работы их E-commerce платформы.<\/li>\n<li><b>Didi:<\/b> Масштабное использование для логистики в реальном времени и анализа поездок.<\/li>\n<li><b>Fanatics:<\/b> Сократили расходы на 90%, перейдя с Snowflake на связку StarRocks + Iceberg.<\/li>\n<li><b>Coinbase:<\/b> Заменили Snowflake для аналитики, обращенной к клиенту (customer-facing). Требовались быстрые JOIN-ы на терабайтных масштабах, чего не давали другие системы.<\/li>\n<\/ol>\n<p><b>Уровень 2: Strategic Users (Важные продуктовые внедрения)<\/b><\/p>\n<p>Компании, использующие StarRocks для конкретных, высоконагруженных продуктов или функций.<\/p>\n<ol start=\"1\">\n<li><b>Pinterest:<\/b> Используют для аналитики, но акцент сделан на Lakehouse-архитектуре и join-ах больших таблиц.<\/li>\n<li><b>Xiaohongshu (RedNote):<\/b> Аналитика поведения пользователей в реальном времени (user behavior analysis) с высочайшей кардинальностью данных.<\/li>\n<li><b>Fresha:<\/b> Аналитика для партнеров (салонов красоты). Важна скорость отклика дэшбордов для тысяч внешних пользователей.<\/li>\n<li><b>Grab:<\/b> Аналитика для супер-приложения. Замена Druid\/Pinot для более гибких SQL-запросов.<\/li>\n<li><b>Celonis:<\/b> Использование в движке Process Mining, где требуются сложные JOIN-операции, с которыми StarRocks справляется лучше колоночных аналогов.<\/li>\n<\/ol>\n<p><b>Уровень 3: Adopters (Специфические сценарии)<\/b><\/p>\n<p>Компании, использующие StarRocks для внутренних BI-систем, маркетинговой аналитики или замены медленных компонентов.<\/p>\n<ul>\n<li>Airtable, Cisco, Intuit, Zepto, PlaySimple Games:** Вероятнее всего, использование для внутренней ускоренной аналитики и BI-отчетов, где традиционные DWH стали слишком медленными или дорогими.<\/li>\n<\/ul>\n<hr \/>\n<h4>3. Ранжирование по степени влияния на проект (Contribution & Influence)<\/h4>\n<p>StarRocks — это Open Source проект. Влияние оценивается по вкладу в код (Pull Requests), участию в техническом комитете (TSC) и архитектурном развитии.<\/p>\n<p><b>1. Лидеры (Архитекторы и основные контрибьюторы):<\/b><\/p>\n<ul>\n<li>Alibaba и Tencent:** Эти техногиганты не просто используют проект, они предоставляют огромное количество коммитов, тестируют его на экстремальных нагрузках и формируют roadmap развития. Многие фичи для “реального времени” и интеграции с Data Lake пришли благодаря требованиям и коду инженеров этих компаний.<\/li>\n<li>Didi:** Активные контрибьюторы в области стабильности и оптимизации планировщика запросов под высокие нагрузки.<\/li>\n<li>Airbnb:** Их вклад значителен в области интеграции с экосистемой данных (например, улучшения для Apache Iceberg и метрик), так как они строят сложные платформы данных (Minerva).<\/li>\n<\/ul>\n<p><b>2. Инноваторы (Драйверы конкретных фич):<\/b><\/p>\n<ul>\n<li>Trip.com:<b> Сильно повлияли на развитие функций для работы с **Data Lakehouse<\/b> (прямые запросы к Hive\/Iceberg без импорта данных), так как их основной кейс — отказ от миграции данных.<\/li>\n<li>Shopee:<b> Влияют на развитие функционала **Materialized Views<\/b> (материализованных представлений), так как активно используют их для ускорения API.<\/li>\n<li>Pinterest и Coinbase:** Их кейсы (быстрые JOIN-ы на S3) подталкивают развитие кеширования и оптимизатора для “холодных” данных.<\/li>\n<\/ul>\n<p><b>3. Евангелисты (Популяризаторы):<\/b><\/p>\n<ul>\n<li>Celonis, Fanatics, Grab:** Активно выступают на конференциях, пишут технические блоги о миграции с конкурентов (Snowflake, Druid), тем самым привлекая новых пользователей и валидируя технологию на западном рынке.<\/li>\n<\/ul>\n<hr \/>\n<p><b>ClickHouse<\/b> — это колоночная аналитическая СУБД с открытым кодом, позволяющая выполнять аналитические запросы в режиме реального времени на структурированных больших данных. Изначально разработанная в Яндексе для Яндекс.Метрики, она стала мировым стандартом для задач логирования, телеметрии и продуктовой аналитики благодаря феноменальной скорости вставки и сжатия данных.<\/p>\n<h4>1. Сферы деятельности компаний<\/h4>\n<p>Список компаний, использующих ClickHouse, охватывает почти все отрасли, где генерируются “Big Data”.<\/p>\n<p><b>Технологии, Интернет и Облачные сервисы:<\/b><\/p>\n<ul>\n<li>Yandex:** Родительская компания. Поисковик, такси, e-commerce, облачные сервисы.<\/li>\n<li>Cloudflare:** Глобальная сеть доставки контента (CDN) и защита от DDoS.<\/li>\n<li>Uber:** Мировой агрегатор такси и доставки.<\/li>\n<li>eBay:** Один из старейших и крупнейших аукционов и маркетплейсов в мире.<\/li>\n<li>VK (ВКонтакте):** Крупнейшая социальная сеть в СНГ.<\/li>\n<li>GitLab:** Платформа для DevOps и управления жизненным циклом ПО.<\/li>\n<\/ul>\n<p><b>Стриминг, Медиа и Развлечения:<\/b><\/p>\n<ul>\n<li>Spotify:** Глобальный аудио-стриминговый сервис.<\/li>\n<li>Netflix:** Крупнейший в мире онлайн-кинотеатр (стриминг видео).<\/li>\n<li>Twitch:** Видеостриминговый сервис, специализирующийся на компьютерных играх.<\/li>\n<li>Disney+ (Disney Streaming):** Стриминговая платформа медиа-конгломерата Disney.<\/li>\n<\/ul>\n<p><b>Финансы и Финтех:<\/b><\/p>\n<ul>\n<li>Bloomberg:** Поставщик финансовой информации для профессиональных участников рынков.<\/li>\n<li>Deutsche Bank:** Крупнейший банковский концерн Германии.<\/li>\n<li>Revolut:** Британский финтех-стартап и необанк.<\/li>\n<\/ul>\n<p><b>Мониторинг, Observability и SaaS:<\/b><\/p>\n<ul>\n<li>Datadog:** Платформа мониторинга и безопасности для облачных приложений.<\/li>\n<li>Grafana Labs:** Разработчик популярнейшей платформы визуализации данных.<\/li>\n<li>Sentry:** Платформа для отслеживания ошибок в приложениях.<\/li>\n<li>Segment (Twilio):** Платформа клиентских данных (CDP).<\/li>\n<\/ul>\n<p><b>Телеком:<\/b><\/p>\n<ul>\n<li>Comcast:** Крупнейшая телекоммуникационная компания США.<\/li>\n<li>Verizon:** Один из лидеров американского рынка мобильной связи.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>2. Ранжирование по степени использования (Use Case Depth)<\/h4>\n<p>Это ранжирование отражает масштаб данных, критичность системы для бизнеса и сложность архитектуры.<\/p>\n<p><b>Уровень 1: Heavy Users \/ Hyper-scale (Экстремальные нагрузки)<\/b><\/p>\n<p>Компании, обрабатывающие триллионы строк, где ClickHouse является ядром инфраструктуры.<\/p>\n<ol start=\"1\">\n<li><b>Cloudflare:<\/b> Пожалуй, один из самых впечатляющих кейсов в мире. Используют ClickHouse для аналитики HTTP-трафика и DNS-запросов. Обрабатывают <b>десятки миллионов событий в секунду<\/b> (более 100 млрд строк в день) для предоставления аналитики клиентам в личном кабинете.<\/li>\n<li><b>Yandex (Метрика):<\/b> Исторический “reference implementation”. Крупнейшая система веб-аналитики в Европе, работающая на кластерах из сотен серверов. Именно для этой нагрузки (>1 триллиона строк в базе) ClickHouse и был создан.<\/li>\n<li><b>Uber:<\/b> Используют ClickHouse для своей платформы логирования (более 4 петабайт данных), заменив Elasticsearch в ряде задач ради экономии ресурсов и скорости.<\/li>\n<li><b>Lyft:<\/b> Используют для аналитики поездок и Geo-данных в реальном времени, обрабатывая огромные потоки телеметрии с автомобилей и приложений.<\/li>\n<li><b>Bytedance (TikTok):<\/b> (До миграции части нагрузок на другие системы) Один из крупнейших пользователей в Китае, использовавший ClickHouse для анализа поведения пользователей (User Behavior Analysis) на гигантских масштабах.<\/li>\n<\/ol>\n<p><b>Уровень 2: Strategic Users (Ключевой компонент продукта)<\/b><\/p>\n<p>Компании, которые строят свой основной продукт или критически важные внутренние сервисы на базе ClickHouse.<\/p>\n<ol start=\"1\">\n<li><b>Sentry:<\/b> Вся аналитика ошибок и производительности в их SaaS-продукте построена на ClickHouse. Они хранят миллиарды событий ошибок, позволяя разработчикам мгновенно фильтровать их.<\/li>\n<li><b>GitLab:<\/b> Используют ClickHouse для feature “Observability” внутри своего продукта, предоставляя пользователям аналитику по их CI\/CD пайплайнам.<\/li>\n<li><b>Spotify:<\/b> Используют для внутренней аналитики экспериментов (A\/B тесты) и логов воспроизведения треков.<\/li>\n<li><b>eBay:<\/b> Используют для OLAP-аналитики логов приложений и мониторинга, добиваясь снижения затрат по сравнению с традиционными коммерческими решениями.<\/li>\n<li><b>Segment:<\/b> Платформа позволяет клиентам делать сложные выборки по аудитории, и ClickHouse здесь выступает в роли “движка” для мгновенной сегментации пользователей.<\/li>\n<\/ol>\n<p><b>Уровень 3: Adopters (Специализированные задачи)<\/b><\/p>\n<p>Использование для конкретных департаментов, внутренней бизнес-разведки (BI) или замены старых компонентов.<\/p>\n<ul>\n<li>Deutsche Bank:** Анализ рыночных тиков и высокочастотная финансовая аналитика.<\/li>\n<li>Comcast:** Мониторинг качества видеопотока и сети.<\/li>\n<li>Bloomberg:** Аналитика взаимодействия пользователей с терминалом Bloomberg.<\/li>\n<\/ul>\n<p>---<\/p>\n<h4>3. Ранжирование по степени влияния на проект (Contribution & Influence)<\/h4>\n<p>ClickHouse имеет огромное сообщество. Влияние оценивается не только по использованию, но и по вкладу в кодовую базу (PR), разработке драйверов и организации митапов.<\/p>\n<p><b>1. Создатели и Архитекторы:<\/b><\/p>\n<ul>\n<li>ClickHouse Inc:** После выделения в отдельную компанию в 2021 году, основные разработчики (включая Алексея Миловидова) работают здесь. Именно они определяют roadmap, развивают ClickHouse Cloud и ядро системы.<\/li>\n<li>Yandex:** Исторический создатель. До сих пор вносят огромный вклад, поддерживают свои форки и используют систему на пределе возможностей, что помогает выявлять баги производительности.<\/li>\n<\/ul>\n<p><b>2. Технологические Партнеры и Контрибьюторы:<\/b><\/p>\n<ul>\n<li>Cloudflare:** Внесли огромный вклад в оптимизацию работы с сетью, TLS и безопасность, так как их требования к защищенности и нагрузке экстремальны. Часто пишут глубокие технические статьи о внутренностях ClickHouse.<\/li>\n<li>Altinity:** Компания, оказывающая консалтинг и поддержку ClickHouse. Сделали огромный вклад в экосистему Kubernetes (ClickHouse Operator), драйверы и интеграцию с экосистемой Hadoop\/MySQL.<\/li>\n<li>Contentsquare:** Активно участвуют в оптимизации ядра для специфических аналитических функций (session analysis).<\/li>\n<\/ul>\n<p><b>3. Евангелисты Экосистемы:<\/b><\/p>\n<ul>\n<li>Uber и Lyft:** Публикуют детальные инженерные блоги о том, как переводить логирование с ELK стека на ClickHouse, чем вдохновили сотни других компаний на миграцию.<\/li>\n<li>Grafana Labs:** Разрабатывают и поддерживают официальный плагин ClickHouse для Grafana, делая СУБД доступной для визуализации миллионам пользователей.<\/li>\n<\/ul>\n",
            "date_published": "2026-03-06T01:26:35+03:00",
            "date_modified": "2026-03-13T21:32:49+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image.png-1.jpg",
            "_date_published_rfc2822": "Fri, 06 Mar 2026 01:26:35 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "320",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image.png-1.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Screenshot-from-2026-03-06-01-15-33.png",
                    "https:\/\/gavrilov.info\/pictures\/image.png.jpg"
                ]
            }
        },
        {
            "id": "319",
            "url": "https:\/\/gavrilov.info\/all\/r2-sql-glubokoe-pogruzhenie-v-nash-novy-dvizhok-dlya-raspredelen\/",
            "title": "R2 SQL: Глубокое погружение в наш новый движок для распределенных запросов",
            "content_html": "<h4>Введение<\/h4>\n<p>В современном мире объемы данных растут экспоненциально, и хранение петабайтов информации в объектных хранилищах (как Amazon S3 или Cloudflare R2) стало стандартом. Однако просто хранить данные мало — их нужно анализировать. Традиционно для этого требовалось поднимать сложные кластеры (например, Spark или Trino), что долго и дорого.<\/p>\n<p>Компания Cloudflare представила <b>R2 SQL<\/b> — бессерверный (serverless) движок, который позволяет выполнять SQL-запросы прямо к данным, лежащим в объектном хранилище R2, без необходимости управлять инфраструктурой. Эта статья подробно описывает архитектуру этого решения: как они добились высокой скорости, используя формат таблиц Apache Iceberg, умное планирование запросов и свою глобальную сеть.<\/p>\n<p><a href=\"https:\/\/blog.cloudflare.com\/r2-sql-deep-dive\/\">Ссылка на оригинал статьи<\/a> А ранее я уже писал про их анонс тут <a href=\"https:\/\/gavrilov.info\/all\/cloudflare-anonsiruet-platformu-dannyh\/\">https:\/\/gavrilov.info\/all\/cloudflare-anonsiruet-platformu-dannyh\/<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-18-v-21.51.06.png\" width=\"1582\" height=\"540\" alt=\"\" \/>\n<\/div>\n<hr \/>\n<h4>R2 SQL: Глубокое погружение в наш новый движок для распределенных запросов<\/h4>\n<p><b>Авторы:<\/b> Yevgen Safronov, Nikita Lapkov, Jérôme Schneider. ( Привет Никита и Евген :)<\/p>\n<p>Как выполнить SQL-запросы над петабайтами данных… без сервера?<br \/>\nУ нас есть ответ: <b>R2 SQL<\/b>, бессерверный движок запросов, который может просеивать огромные наборы данных и возвращать результаты за секунды.<\/p>\n<p>В этом посте подробно описывается архитектура и методы, которые делают это возможным. Мы пройдемся по нашему <b>Планировщику запросов<\/b> (Query Planner), который использует `R2 Data Catalog` для отсечения терабайтов данных еще до чтения первого байта, и объясним, как мы распределяем работу по глобальной сети Cloudflare, используя `Workers` и `R2` для массивного параллельного выполнения.<\/p>\n<h5>От каталога к запросу<\/h5>\n<p>Во время Developer Week 2025 мы запустили `R2 Data Catalog` — управляемый каталог `Apache Iceberg`, встроенный непосредственно в ваш бакет Cloudflare R2. Iceberg — это открытый формат таблиц, который предоставляет критически важные функции баз данных (такие как транзакции и эволюция схемы) для объектного хранилища петабайтного масштаба. Он дает вам надежный каталог ваших данных, но сам по себе не предоставляет способа их запрашивать.<\/p>\n<p>До сих пор чтение вашего каталога `R2 Data Catalog` требовало настройки отдельного сервиса, такого как `Apache Spark` или Trino. Эксплуатация этих движков в большом масштабе непроста: вам нужно создавать кластеры, управлять использованием ресурсов и отвечать за их доступность — ничто из этого не способствует главной цели: получению ценности из ваших данных.<\/p>\n<p>`R2 SQL` полностью устраняет этот этап. Это бессерверный движок запросов, который выполняет SQL-запросы на чтение (retrieval) к вашим таблицам Iceberg прямо там, где живут ваши данные.<\/p>\n<p><b>поясненИИе: Что такое Apache Iceberg?<\/b><\/summary><\/p>\n<p>Представьте, что у вас есть огромная куча файлов (CSV, Parquet, JSON) в облачном хранилище. Это “озеро данных”. Проблема в том, что если вы начнете менять один файл, пока кто-то другой его читает, все сломается. Трудно понять, какая версия данных актуальна.<\/p>\n<p><b>Apache Iceberg<\/b> — это слой управления поверх этих файлов. Он работает как библиотекарь: он не хранит сами книги (данные), но ведет идеальный учет (метаданные). Он точно знает: “Таблица ‘Пользователи’ сейчас состоит из вот этих 100 файлов”.<br \/>\nЭто позволяет делать с обычными файлами в облаке то, что раньше умели только дорогие базы данных:<\/p>\n<ol start=\"1\">\n<li><b>ACID-транзакции:<\/b> Гарантия того, что данные не запишутся “наполовину”.<\/li>\n<li><b>Time Travel:<\/b> Возможность сделать запрос “Как выглядела таблица вчера в 14:00?”.<\/li>\n<li><b>Ecosystem:<\/b> Единый стандарт, который понимают разные инструменты аналитики.<\/li>\n<\/ol>\n<h5>Проектирование движка запросов для петабайтов<\/h5>\n<p>Объектное хранилище фундаментально отличается от хранилища традиционной базы данных. База данных структурирована по своей природе; `R2 `— это океан объектов, где одна логическая таблица может состоять из миллионов отдельных файлов, больших и маленьких, и новые поступают каждую секунду.<\/p>\n<p>Apache Iceberg предоставляет мощный слой логической организации поверх этой реальности. Он работает, управляя состоянием таблицы как неизменяемой серией мгновенных снимков (snapshots), создавая надежное, структурированное представление таблицы путем манипулирования “легкими” файлами метаданных вместо перезаписи самих файлов данных.<\/p>\n<p>Однако эта логическая структура не меняет физической проблемы, лежащей в основе: эффективный движок запросов всё равно должен найти конкретные данные, необходимые ему, в этой огромной коллекции файлов. Это требует преодоления двух основных технических барьеров:<\/p>\n<ol start=\"1\">\n<li><b>Проблема ввода-вывода (I\/O problem):<\/b> Главная проблема эффективности запросов — минимизация объема данных, считываемых из хранилища. Подход “в лоб” с чтением каждого объекта просто нежизнеспособен. Основная цель — читать только те данные, которые абсолютно необходимы.<\/li>\n<li><b>Проблема вычислений (Compute problem):<\/b> Объем данных, которые *действительно* нужно прочитать, все равно может быть огромным. Нам нужен способ выделить запросу, который может быть массивным, необходимое количество вычислительной мощности всего на несколько секунд, а затем мгновенно снизить его до нуля, чтобы избежать лишних трат.<\/li>\n<\/ol>\n<p>Наша архитектура для `R2 SQL` разработана для решения этих двух проблем с помощью двухэтапного подхода: <b>Планировщик запросов<\/b> (Query Planner), который использует метаданные для интеллектуального отсечения (pruning) пространства поиска, и система <b>Выполнения запросов<\/b> (Query Execution), которая распределяет работу по глобальной сети Cloudflare для параллельной обработки данных.<\/p>\n<h5>Планировщик запросов (Query Planner)<\/h5>\n<p>Самый эффективный способ обработки данных — не читать их вовсе. Это ключевая стратегия планировщика `R2 SQL`. Вместо исчерпывающего сканирования каждого файла планировщик использует структуру метаданных, предоставляемую каталогом `R2 Data Catalog`, чтобы “подрезать” пространство поиска, то есть избежать чтения огромных массивов данных, не относящихся к запросу.<\/p>\n<p>Это расследование “сверху вниз”, где планировщик перемещается по иерархии слоев метаданных Iceberg, используя статистику (<b>stats<\/b>) на каждом уровне для построения быстрого плана, точно указывающего, какие диапазоны байтов должен прочитать движок.<\/p>\n<h6>Что мы подразумеваем под “статистикой”?<\/h6>\n<p>Когда мы говорим, что планировщик использует “статы”, мы имеем в виду сводные метаданные, которые Iceberg хранит о содержимом файлов данных. Эта статистика создает грубую карту данных, позволяя планировщику принимать решения о том, какие файлы читать, а какие игнорировать, даже не открывая их.<\/p>\n<p>Есть два основных уровня статистики, которые планировщик использует для отсечения (pruning):<\/p>\n<ol start=\"1\">\n<li><b>Статистика уровня раздела (Partition-level stats):<\/b> Хранится в списке манифестов (manifest list) Iceberg. Эти статы описывают диапазон значений разделов для всех данных в определенном файле манифеста Iceberg. Для раздела по `day(event_timestamp)` это будут самый ранний и самый поздний дни, присутствующие в файлах, отслеживаемых этим манифестом.<\/li>\n<li><b>Статистика уровня столбца (Column-level stats):<\/b> Хранится в файлах манифестов. Это более детальная статистика о каждом отдельном файле данных. Файлы данных в `R2 Data Catalog` отформатированы с использованием `Apache Parquet`. Для каждого столбца файла Parquet манифест хранит ключевую информацию, такую как:\n<ul>\n  <li>Минимальное и максимальное значения. Если запрос запрашивает `http_status = 500`, а статистика файла показывает, что в столбце `http_status` минимум 200 и максимум 404, этот файл можно пропустить целиком.<\/li>\n  <li>Количество null-значений. Это позволяет планировщику пропускать файлы, когда запрос ищет конкретно non-null значения (например, `WHERE error_code IS NOT NULL`), а метаданные файла сообщают, что все значения для `error_code` являются null.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h6>Отсечение пространства поиска (Pruning)<\/h6>\n<p>Процесс отсечения — это расследование “сверху вниз”, которое происходит в три основных этапа:<\/p>\n<ol start=\"1\">\n<li><b>Метаданные таблицы и текущий снимок (snapshot):<\/b>  <br \/>\nПланировщик начинает с запроса к каталогу о местоположении текущих метаданных таблицы. Это JSON-файл, содержащий текущую схему таблицы, спецификации разделов и журнал всех исторических снимков. Затем планировщик выбирает последний снимок для работы.<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Список манифестов и отсечение разделов:<\/b>  <br \/>\nТекущий снимок указывает на единый *список манифестов* (manifest list) Iceberg. Планировщик читает этот файл и использует статистику уровня разделов для каждой записи, чтобы выполнить первый, самый мощный шаг отсечения, отбрасывая любые манифесты, чьи диапазоны значений разделов не удовлетворяют запросу. Например, для таблицы, партиционированной по дням, планировщик может отбросить манифесты за ненужные даты.<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Манифесты и отсечение на уровне файлов:<\/b>  <br \/>\nДля оставшихся манифестов планировщик читает каждый из них, чтобы получить список фактических файлов данных Parquet. Эти файлы манифестов содержат более детальную статистику уровня столбцов. Это позволяет выполнить второй шаг отсечения, отбрасывая целые файлы данных, которые не могут содержать строки, соответствующие фильтрам запроса.<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Отсечение групп строк (Row-group pruning) внутри файла:<\/b>  <br \/>\nНаконец, для конкретных файлов данных, которые всё еще являются кандидатами, Планировщик использует статистику, хранящуюся внутри *футеров* (footers) файлов Parquet, чтобы пропускать целые группы строк (row groups).<\/li>\n<\/ol>\n<p>Результатом этого многослойного отсечения является точный список файлов Parquet и групп строк внутри этих файлов. Они становятся рабочими единицами (work units), которые отправляются в систему Выполнения запросов.<\/p>\n<p><b>поясненИИе: Формат Parquet и Row Groups<\/b><\/p>\n<p><b>Apache Parquet<\/b> — это колоночный формат хранения данных. В отличие от CSV, где данные хранятся строка за строкой, в Parquet данные хранятся столбец за столбцом. Это идеально для аналитики (когда вам нужно посчитать среднее по одной колонке, не читая остальные 50).<\/p>\n<p>Внутри себя файл Parquet делится на <b>Row Groups<\/b> (группы строк). Представьте файл на 1 миллион строк. Он может быть разбит на 10 групп по 100,000 строк. У каждой группы есть свой мини-заголовок со статистикой (min\/max значения).<\/p>\n<p><b>Пример:<\/b> Вы ищете `id = 950,000`.<br \/>\nДвижок читает футер файла и видит:<\/p>\n<ul>\n<li>Row Group 1: id 1-100,000 -> Пропускаем.<\/li>\n<li>...<\/li>\n<li>Row Group 10: id 900,001-1,000,000 -> <b>Читаем только эту часть файла<\/b>.<\/li>\n<\/ul>\n<p>Это называется “I\/O skipping” и экономит огромное количество времени и денег на трафике.<\/p>\n<h5>Конвейер планирования (The Planning pipeline)<\/h5>\n<p>В `R2 SQL` описанное выше многослойное отсечение не является монолитным процессом. Для таблицы с миллионами файлов метаданные могут быть слишком большими, чтобы обработать их полностью до начала реальной работы. Ожидание полного плана внесет значительную задержку (latency).<\/p>\n<p>Вместо этого `R2 SQL` рассматривает планирование и выполнение как единый конкурентный конвейер (pipeline). Работа планировщика — производить поток рабочих единиц (work units), которые исполнитель (executor) потребляет, как только они становятся доступны.<\/p>\n<h6>Начало выполнения как можно раньше<\/h6>\n<p>С этого момента запрос обрабатывается в потоковом режиме. По мере того как Планировщик читает файлы манифестов (и, следовательно, файлы данных, на которые они указывают) и отсекает их, он немедленно отправляет любые подходящие файлы данных\/группы строк как рабочие единицы в очередь выполнения.<\/p>\n<p>Такая конвейерная структура гарантирует, что вычислительные узлы могут начать дорогую работу по вводу-выводу данных практически мгновенно, задолго до того, как планировщик закончит свое полное расследование.<\/p>\n<p>На вершине этой модели конвейера планировщик добавляет критически важную оптимизацию: <b>преднамеренное упорядочивание<\/b> (deliberate ordering). Файлы манифестов не стримятся в случайной последовательности. Вместо этого планировщик обрабатывает их в порядке, соответствующем условию `ORDER BY` вашего запроса, руководствуясь статистикой метаданных. Это гарантирует, что данные, которые с наибольшей вероятностью содержат желаемые результаты, обрабатываются первыми.<\/p>\n<h6>Ранняя остановка: как закончить, не читая всё<\/h6>\n<p>Благодаря тому, что Планировщик передает рабочие единицы в порядке, соответствующем `ORDER BY`, система выполнения сначала обрабатывает данные, которые с наибольшей вероятностью попадут в итоговый набор результатов.<\/p>\n<p>Например, для запроса типа `... ORDER BY timestamp DESC LIMIT 5`: по мере того как движок выполнения обрабатывает рабочие единицы и отправляет результаты обратно, планировщик одновременно делает две вещи:<\/p>\n<ol start=\"1\">\n<li>Поддерживает ограниченную “кучу” (heap) из лучших 5 результатов, увиденных на данный момент.<\/li>\n<li>Следит за “ватерлинией” (high-water mark) самого потока. Благодаря метаданным он всегда знает абсолютно самый поздний `timestamp` любого файла данных, который *еще не был* обработан.<\/li>\n<\/ol>\n<p>В момент, когда самая старая временная метка в нашей “Топ-5 куче” оказывается новее, чем “ватерлиния” оставшегося потока (максимально возможная дата в еще не прочитанных файлах), <b>весь запрос может быть остановлен<\/b>.<\/p>\n<p>В этот момент мы можем доказать, что ни одна оставшаяся рабочая единица не может содержать результат, который попал бы в топ-5. Конвейер останавливается, и пользователю возвращается полный, корректный результат, часто после чтения лишь крошечной доли потенциально подходящих данных.<\/p>\n<hr \/>\n<h5>Выполнение запросов (Query Execution)<\/h5>\n<p>Планировщик передает работу кусочками, называемыми <b>Row Groups<\/b>. Сервер, который получает запрос пользователя, берет на себя роль <b>координатора запроса<\/b>. Он распределяет работу между <b>воркерами<\/b> (query workers) и агрегирует результаты.<\/p>\n<p>Сеть Cloudflare огромна. Координатор связывается с внутренним API Cloudflare, чтобы убедиться, что для выполнения выбираются только здоровые серверы. Соединения между координатором и воркерами проходят через `Cloudflare Argo Smart Routing` для обеспечения быстрой и надежной связи.<\/p>\n<p>Серверы, получающие задачи от координатора, становятся воркерами. Они служат точкой горизонтального масштабирования в `R2 SQL`. При большем количестве воркеров `R2 SQL` может обрабатывать запросы быстрее, распределяя работу между множеством серверов. Это особенно актуально для запросов, охватывающих большие объемы файлов.<\/p>\n<h6>Внутреннее устройство: Apache DataFusion<\/h6>\n<p>Внутри каждый воркер использует `Apache DataFusion` для выполнения SQL-запросов к группам строк. `DataFusion` — это аналитический движок запросов с открытым исходным кодом, написанный на <b>Rust<\/b>.<\/p>\n<p>Разделы (partitions) в `DataFusion` идеально ложатся на модель данных `R2 SQL`, поскольку каждая группа строк (row group) может рассматриваться как независимый раздел. Благодаря этому каждая группа строк обрабатывается параллельно.<br \/>\nПоскольку группы строк обычно содержат как минимум 1000 строк, `R2 SQL` выигрывает от <b>векторизованного выполнения<\/b>. Каждый поток DataFusion может выполнять SQL-запрос сразу на множестве строк за один проход, амортизируя накладные расходы на интерпретацию запроса.<\/p>\n<h6>Поддержка Parquet и Arrow<\/h6>\n<p>`DataFusion` имеет первоклассную поддержку Parquet. Используя ranged reads (чтение диапазонов) в R2, он способен считывать только части файлов Parquet, содержащие запрошенные столбцы, пропуская остальные.<\/p>\n<p>Оптимизатор `DataFusion` также позволяет нам “проталкивать” фильтры (push down filters) на самые низкие уровни плана запроса. Другими словами, мы можем применять фильтры прямо в момент чтения значений из файлов Parquet.<\/p>\n<p>Когда воркер заканчивает вычисления, он возвращает результаты координатору через протокол <b>gRPC<\/b>. `R2 SQL` использует `Apache Arrow` для внутреннего представления результатов. Это формат в оперативной памяти (in-memory), который эффективно представляет массивы структурированных данных. Arrow также определяет формат сериализации `Arrow IPC`, который идеально подходит для передачи данных между процессами по сети.<\/p>\n<p><b>поясненИИе: Векторизация и Apache Arrow<\/b><\/summary><br \/>\n<b>Векторизованное выполнение (Vectorized execution):<\/b> Традиционные базы данных обрабатывали одну строку за раз (Row-at-a-time). Это медленно, потому что процессор постоянно переключается. Векторизация означает обработку данных “пачками” (например, сложить сразу 1000 чисел из колонки А с 1000 чисел из колонки Б). Это использует современные возможности CPU (SIMD инструкции) и работает в разы быстрее.<\/p>\n<p><b>Apache Arrow:<\/b> Это стандарт того, как хранить эти “пачки” данных в оперативной памяти, чтобы процессору было максимально удобно их читать.<br \/>\nГлавный плюс Arrow: <b>Zero-copy<\/b>. Если один инструмент (DataFusion) передает данные другому (по сети координатору), и оба понимают Arrow, им не нужно тратить время на перекодирование (сериализацию\/десериализацию) данных. Они просто “передают указатель” или копируют сырые байты как есть.<\/p>\n<h5>Будущие планы<\/h5>\n<p>Хотя `R2 SQL` и так хорош в фильтрации, мы планируем быстро добавлять новые возможности:<\/p>\n<ul>\n<li>Поддержка сложных агрегаций (GROUP BY) в распределенном и масштабируемом виде.<\/li>\n<li>Инструменты для визуализации выполнения запросов (explain analyze), чтобы помочь разработчикам улучшать производительность.<\/li>\n<li>Поддержка многих конфигурационных опций Apache Iceberg.<\/li>\n<li>Возможность запрашивать каталоги прямо из панели управления Cloudflare (Dashboard).<\/li>\n<\/ul>\n<p>Мы также исследуем различные виды индексов, чтобы сделать запросы еще быстрее, и планируем добавить полнотекстовый поиск, геопространственные запросы и многое другое.<\/p>\n<h5>Попробуйте сейчас!<\/h5>\n<p>Это ранние дни для `R2 SQL`, но он уже доступен в открытой бете! Переходите к нашему руководству по началу работы, чтобы создать сквозной конвейер данных. Мы ждем вашей обратной связи в нашем Discord для разработчиков.<\/p>\n<p>***<\/p>\n<h4>Итог и СоображенИИя<\/h4>\n<p><b>Итог:<\/b> Cloudflare выпустила мощный инструмент, который превращает их объектное хранилище (R2) в полноценную аналитическую базу данных. Используя открытые стандарты (Iceberg, Parquet, Arrow, DataFusion) и свою глобальную сеть периферийных вычислений (Edge), они решили главную проблему Big Data — необходимость платить за простой серверов. Здесь вы платите только за время выполнения конкретного SQL-запроса.<\/p>\n<p><b>СоображенИИя:<\/b><\/p>\n<ol start=\"1\">\n<li><b>Коммодитизация аналитики:<\/b> Cloudflare делает с Big Data то же, что ранее сделала с CDN и защитой от DDoS — делает сложные энтерпрайз-технологии доступными “по кнопке”. Использование открытого стека (Rust + Arrow + DataFusion) — это сейчас золотой стандарт построения современных СУБД (по этому пути идут такие гиганты как InfluxDB 3.0, LanceDB и др.). Cloudflare не изобретает велосипед, а собирает очень быструю ракету из лучших деталей.<\/li>\n<li><b>Убийца Snowflake\/Databricks для “бедных”?<\/b> Для огромных корпораций Snowflake и Databricks останутся стандартом из-за богатого функционала. Но для стартапов и среднего бизнеса, у которых данные лежат в R2 (чтобы не платить за egress трафик AWS), появление R2 SQL делает переезд на сторонние аналитические платформы бессмысленным. Зачем гонять данные туда-сюда, если можно выполнить SQL прямо “на месте”?<\/li>\n<li><b>Синергия с ИИ:<\/b> Упоминание планов на “индексы” и “геопространственные запросы” намекает на векторный поиск в будущем. Если Cloudflare добавит возможность делать векторный поиск по данным в R2 так же нативно, это станет киллер-фичей для всех, кто строит RAG (Retrieval-Augmented Generation) приложения на базе LLM. Хранишь документы в R2 -> R2 SQL ищет контекст -> Workers AI генерируют ответ. Весь цикл внутри одной экосистемы с минимальными задержками.<\/li>\n<\/ol>\n<p>Еще можно почитать про <a href=\"https:\/\/vegafusion.io\">https:\/\/vegafusion.io<\/a> и про формат <a href=\"https:\/\/lance.org\">https:\/\/lance.org<\/a> – он как раз и добавит векторочков.<\/p>\n",
            "date_published": "2026-02-18T21:56:56+03:00",
            "date_modified": "2026-02-18T21:57:57+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer",
                "Platform",
                "Serverless"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-18-v-21.51.06.png",
            "_date_published_rfc2822": "Wed, 18 Feb 2026 21:56:56 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "319",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-18-v-21.51.06.png"
                ]
            }
        },
        {
            "id": "317",
            "url": "https:\/\/gavrilov.info\/all\/data-stack-2-0-zakat-lambda-arhitektury-i-voshod-fluss-s-lance\/",
            "title": "Data Stack 2.0: Закат Lambda-архитектуры и восход Fluss с Lance",
            "content_html": "<h2>Data Stack 2.0: Закат Lambda-архитектуры и восход Fluss с Lance<\/h2>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-13-v-01.58.40.png\" width=\"1796\" height=\"340\" alt=\"\" \/>\n<\/div>\n<p>В мире инфраструктуры данных происходит “тектонический сдвиг”, описанный в отчетах <a href=\"https:\/\/a16z.com\/emerging-architectures-for-modern-data-infrastructure\/\">a16z.com<\/a>. Индустрия отходит от сложной Lambda-архитектуры (где batch и streaming живут отдельно) к унифицированным решениям, которые называют <b>Streamhouse<\/b>.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-13-v-01.59.13.png\" width=\"1476\" height=\"412\" alt=\"\" \/>\n<\/div>\n<p>Два ключевых игрока, меняющих правила игры в этом переходе:<\/p>\n<ol start=\"1\">\n<li><b>Apache Fluss<\/b> — управляемое хранилище для потоковой обработки (Streaming Storage).<\/li>\n<li><b>Lance<\/b> — формат данных нового поколения для AI и Data Lake.<\/li>\n<\/ol>\n<h3>1. Проблема: Почему одной Kafka больше недостаточно?<\/h3>\n<p>Долгое время Apache Kafka была стандартом де-факто для передачи данных. Однако, как отмечают эксперты Ververica в статье <a href=\"https:\/\/www.ververica.com\/blog\/a-world-without-kafka\">Мир без Kafka<\/a>, Kafka была спроектирована как *распределенный лог*, а не как база данных.<\/p>\n<p>Перевод есть тут, у меня: <a href=\"https:\/\/gavrilov.info\/all\/mir-bez-kafka-pochemu-kafka-ne-podhodit-dlya-analitiki-realnogo\/\">https:\/\/gavrilov.info\/all\/mir-bez-kafka-pochemu-kafka-ne-podhodit-dlya-analitiki-realnogo\/<\/a><\/p>\n<p><b>Фундаментальные ограничения брокеров сообщений (Kafka\/Pulsar) для аналитики:<\/b><\/p>\n<ul>\n<li><b>Слабая работа с обновлениями (Updates):<\/b> Kafka — это `append-only` система. Реализация `UPDATE` или `DELETE` требует использования *Compact Topics*, что не дает гарантий мгновенной консистентности и сложно в эксплуатации.<\/li>\n<li><b>Медленное чтение истории:<\/b> Чтобы найти запись годичной давности, вам часто нужно прочитать весь лог последовательно (Scan). Сложность операции — $O(N)$.<\/li>\n<li><b>Row-based природа:<\/b> Данные хранятся строками (Message bytes). Для аналитики (OLAP), где нам нужен средний чек по столбцу `price`, системе приходится распаковывать и читать *все* поля сообщения, что неэффективно.<\/li>\n<\/ul>\n<h3>2. Apache Fluss: Недостающее звено для Flink<\/h3>\n<p><a href=\"https:\/\/fluss.apache.org\">Apache Fluss<\/a> создан, чтобы решить проблему “разделения” между потоком и таблицей. Это нативное хранилище для Apache Flink, которое поддерживает <a href=\"https:\/\/www.ververica.com\/blog\/introducing-fluss\">концепцию Fluss<\/a>.<\/p>\n<h4>Архитектурные прорывы:<\/h4>\n<ol start=\"1\">\n<li><b>Гибридная модель чтения (Stream-Table Duality):<\/b> Fluss позволяет читать данные и как бесконечный поток (Log), и как изменяемую таблицу с первичными ключами (Primary Key Table). Это делает реализацию <b>CDC (Change Data Capture)<\/b> тривиальной: обновления перезаписывают старые значения по ключу.<\/li>\n<li><b>Колоночная проекция (Columnar Projection):<\/b> В отличие от Kafka, Fluss может отдавать аналитическому движку (Flink) только нужные колонки. Это снижает нагрузку на сеть (`I\/O`) в разы.<\/li>\n<li><b>Real-Time Lookups:<\/b> Fluss поддерживает точечные запросы (Point Lookup) по первичному ключу с задержкой порядка миллисекунд.  <br \/>\n$$Latency_{Fluss} \\ll Latency_{Kafka Scan}$$  <br \/>\nЭто позволяет использовать его как *Serverless State* для приложений, избавляясь от необходимости ставить рядом Redis или RocksDB.<\/li>\n<li><b>Tiered Storage в Data Lake:<\/b> Fluss работает в паре с <b>Apache Paimon<\/b> (ранее Flink Table Store). Горячие данные живут в Fluss (на быстрых дисках\/RAM), а по мере устаревания автоматически конвертируются в формат Lakehouse (Paimon\/Parquet\/ ну или Iceberg) и уходят в S3.<\/li>\n<\/ol>\n<h3>3. Lance: Новый стандарт для AI в Data Lake<\/h3>\n<p>Если Fluss отвечает за доставку и горячее состояние, то <b>Lance<\/b> меняет подход к хранению холодных данных для задач машинного обучения (ML).<\/p>\n<p>Традиционный формат <b>Parquet<\/b> великолепен для аналитики (сканирование больших диапазонов), но ужасен для AI, где требуется <b>случайный доступ (Random Access)<\/b> для формирования батчей обучения.<\/p>\n<p><a href=\"https:\/\/lance.org\">Lance<\/a> решает эти проблемы:<\/p>\n<ul>\n<li>Случайный доступ:** Lance позволяет извлекать строки по индексу в ~100 раз быстрее Parquet.<\/li>\n<li>Векторный поиск:** Это формат со встроенным векторным индексом (IVF-PQ). Вы можете хранить эмбеддинги прямо в файлах на S3 и выполнять поиск ближайших соседей (ANN) без отдельной VectorDB (вроде Pinecone или Milvus).<\/li>\n<li>Zero-Copy версионирование:** Эффективное управление версиями датасетов без дублирования данных.<\/li>\n<\/ul>\n<h3>4. Сборка пазла: Как это работает вместе<\/h3>\n<p>Современный <b>Streamhouse<\/b> (см. <a href=\"https:\/\/bigdataschool.ru\/blog\/news\/flink\/fluss-for-flink\/\">примеры архитектуры]<\/a><\/p>\n<p>выглядит как-то так:<\/p>\n<p>Схема потока данных (Workflow):<\/p>\n<ol start=\"1\">\n<li><b>Ingestion:<\/b>  <br \/>\nПриложения (на Go, Java, Python) пишут данные.<\/li>\n\n<ul>\n  <li>Важно:* Поскольку Fluss совместим с протоколом Kafka, можно использовать существующие <b>Kafka-клиенты<\/b> в Go-сервисах для записи в Fluss, не дожидаясь нативных библиотек. Но это пока только теория. Сходу я не нашел примеров быстро, но можно использовать GO и Arrow Flight SQL.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Streaming Storage (Fluss):<\/b>  <br \/>\nFluss принимает данные, индексирует первичные ключи и хранит “горячее” окно (например, 24 часа).<\/li>\n\n<ul>\n  <li>Flink* выполняет `JOIN` и агрегации прямо поверх Fluss, используя `Lookup Join` (обогащение данных без сохранения большого стейта внутри Flink).<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Archiving & AI (Paimon\/Lance):<\/b>  <br \/>\nИсторические данные сбрасываются в S3.<\/li>\n\n<ul>\n  <li>Для классической BI-аналитики используется формат <b>Apache Paimon<\/b> или Iceberg.<\/li>\n  <li>Для ML-задач данные конвертируются или хранятся в <b>Lance<\/b>.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Unified Analytics (Trino):<\/b>  <br \/>\nДвижок <a href=\"https:\/\/lance.org\/integrations\/trino\/config\/\">Trino<\/a> позволяет делать SQL-запросы ко всем слоям одновременно. Аналитик пишет один `SELECT`, а Trino забирает свежие данные из Fluss, а исторические — из S3 (Lance\/Parquet\/iceberg).<\/li>\n<\/ol>\n<h4>Пример интеграции (концептуальный)<\/h4>\n<p>Поскольку прямого клиента Go для Fluss нет, использование в микросервисах чаще всего выглядит как работа через Kafka-протокол или HTTP-прокси, а основная логика ложится на Flink (Java\/Python\/ или еще чего):<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">\/\/ Flink SQL example: Создание таблицы, управляемой Fluss\nCREATE TABLE user_behavior (\n    user_id BIGINT,\n    item_id BIGINT,\n    action STRING,\n    ts TIMESTAMP(3),\n    PRIMARY KEY (user_id) NOT ENFORCED\n) WITH (\n    'connector' = 'fluss',\n    'bootstrap.servers' = '...:9092', \/\/ Fluss совместим с Kafka-адресацией\n    'table.log.consistency' = 'eventual' \/\/ Оптимизация под высокую пропускную способность\n);<\/code><\/pre><p>Надо пробовать и тестировать... все таки еще инкубационный и это только теория.<\/p>\n<h3>5. Выводы и рекомендации<\/h3>\n<ol start=\"1\">\n<li><b>Не используйте Kafka как базу данных.<\/b> Если вашей архитектуре требуются частые обновления (`UPSERT`) и точечные запросы (`Lookup`), <a href=\"https:\/\/fluss.apache.org\">Apache Fluss<\/a> — это более подходящий инструмент в экосистеме Flink.<\/li>\n<li><b>Lance для AI.<\/b> Если вы строите RAG (Retrieval-Augmented Generation) или RecSys, рассмотрите формат Lance вместо связки “Parquet + внешняя VectorDB”. Это упростит инфраструктуру.<\/li>\n<li><b>Следите за совместимостью.<\/b> Интеграции Lance с Trino и Fluss с не-JVM языками (например, Go, Rust или еще чего) находятся в активной разработке. Используйте проверенные пути (Kafka Protocol для Ingestion, DataFusion\/Java\/Python для Querying).<\/li>\n<\/ol>\n<h4>Полезные ресурсы для изучения:<\/h4>\n<ul>\n<li><a href=\"https:\/\/a16z.com\/emerging-architectures-for-modern-data-infrastructure\/\">Emerging Architectures for Modern Data Infrastructure (a16z<\/a>)<\/li>\n<li><a href=\"https:\/\/www.ververica.com\/blog\/introducing-fluss\">Introducing Fluss (Ververica<\/a>)<\/li>\n<li><a href=\"https:\/\/bigdataschool.ru\/blog\/news\/flink\/fluss-for-flink\/\">Fluss for Flink (BigDataSchool<\/a>)<\/li>\n<li><a href=\"https:\/\/github.com\/lance-format\/lance-trino\/issues\/29#issuecomment-3893178604\">Lance & Trino Integration Issue (GitHub<\/a><\/li>\n<\/ul>\n",
            "date_published": "2026-02-13T01:59:35+03:00",
            "date_modified": "2026-02-15T13:51:52+03:00",
            "tags": [
                "AI",
                "big data",
                "Data",
                "Data Engineer",
                "MLOps"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-13-v-01.58.40.png",
            "_date_published_rfc2822": "Fri, 13 Feb 2026 01:59:35 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "317",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-13-v-01.58.40.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-13-v-01.59.13.png"
                ]
            }
        },
        {
            "id": "318",
            "url": "https:\/\/gavrilov.info\/all\/mir-bez-kafka-pochemu-kafka-ne-podhodit-dlya-analitiki-realnogo\/",
            "title": "Мир без Kafka: Почему Kafka не подходит для аналитики реального времени, что идет на смену)",
            "content_html": "<p>Статья описывает переход от традиционных систем обмена сообщениями, таких как Apache Kafka, к специализированным решениям для потоковой аналитики, таким как <b>Apache Fluss<\/b>.<\/p>\n<p>Основные тезисы:<\/p>\n<ol start=\"1\">\n<li><b>Проблема Kafka:<\/b> Kafka — это система хранения на основе *записей* (record-based), не имеющая нативной поддержки схем и аналитических возможностей. Это приводит к избыточному чтению данных и перегрузке сети при аналитических запросах, когда нужны только конкретные колонки, а не всё сообщение целиком.<\/li>\n<li><b>Эволюция требований:<\/b> Рынок перешел от простого перемещения данных (ingestion) к сложной аналитике реального времени и AI, что требует более эффективного хранения и доступа к данным.<\/li>\n<li><b>Решение (Apache Fluss):<\/b>\n<ul>\n  <li>Табличная структура:** Данные хранятся как таблицы (Log Tables для логов и PK Tables для изменяемых данных), что обеспечивает строгую типизацию.<\/li>\n  <li>Колоночное хранение:** Использование формата Apache Arrow позволяет читать только нужные колонки (projection pushdown) и эффективнее сжимать данные, что снижает нагрузку на диск и сеть.<\/li>\n  <li>Интеграция с Lakehouse:** Fluss нативно поддерживает многоуровневое хранение (горячие данные в Fluss, теплые\/холодные в S3\/Iceberg\/Paimon) без лишнего копирования, обеспечивая прозрачный доступ к историческим и оперативным данным.<\/li>\n<\/ul>\n<\/li>\n<li><b>Вывод:<\/b> Fluss в связке с Flink предлагает более дешевую, быструю и удобную архитектуру для современной аналитики реального времени, устраняя недостатки Kafka в этой области.<\/li>\n<\/ol>\n<p><b>Ссылка на оригинал:<\/b><br \/>\n<a href=\"https:\/\/www.ververica.com\/blog\/a-world-without-kafka\">Why Kafka Falls Short for Real-Time Analytics (and What Comes Next<\/a><\/p>\n<p>У Apache Kafka был замечательный период: она обеспечивала работу событийно-ориентированных архитектур более десяти лет. Но ландшафт изменился, обнажив явные <b>ограничения Kafka для аналитики в реальном времени<\/b> по мере того, как сценарии использования современной <b>потоковой аналитики<\/b> и принятия решений становятся всё более требовательными. Kafka все чаще пытаются заставить выполнять функции в <b>архитектуре аналитики реального времени<\/b>, для поддержки которых она никогда не проектировалась. Чтобы решить сегодняшние проблемы конвейеров потоковой передачи данных и аналитические требования, необходимы новые возможности. Пришло время для «новичка на районе».<\/p>\n<p>Во время перехода от пакетной обработки к <b>потоковой передаче данных в реальном времени<\/b> значительное внимание и импульс получил проект с открытым исходным кодом, разработанный внутри LinkedIn: <b>Apache Kafka<\/b>. Цель состояла в том, чтобы упростить перемещение данных из точки А в точку Б масштабируемым и устойчивым способом, используя модель издатель\/подписчик. Kafka позволила компаниям создавать ранние <b>конвейеры потоковой передачи данных<\/b> и открыть новый класс событийно-ориентированных сценариев использования. Постоянно растущая экосистема коннекторов и интеграций ускорила внедрение и утвердила Kafka в качестве предпочтительного <b>слоя потокового хранения<\/b>. Однако, по мере того как <b>архитектуры аналитики реального времени<\/b> эволюционировали за пределы простого приема данных (ingestion), ограничения Kafka для аналитических нагрузок становились всё более очевидными.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-233.png\" width=\"1200\" height=\"674\" alt=\"\" \/>\n<\/div>\n<p>С архитектурной точки зрения Kafka — это не аналитический движок. Это устойчивая и масштабируемая <b>система хранения на основе записей (record-based storage system)<\/b> для свежих данных в реальном времени — часто называемая «горячим слоем». Следовательно, аналитические нагрузки должны выполняться за пределами кластера Kafka, постоянно перемещая данные между системами хранения и обработки, что увеличивает сетевой трафик и накладные операционные расходы. Кроме того, Kafka нативно не обеспечивает соблюдение схем для данных, публикуемых в топиках.<\/p>\n<p>Хотя эта гибкость была приемлема для ранних сценариев использования потоковой передачи, современные <b>платформы аналитики реального времени<\/b> требуют схем для обеспечения согласованности, управления и качества данных. В качестве компенсации появились реестры схем (Schema Registries) для обеспечения контрактов между издателями и подписчиками, добавляя сложности аналитическим архитектурам на основе Kafka.<\/p>\n<p>И последнее, но не менее важное (и, возможно, самый важный аспект): Kafka — это система хранения на основе записей. Это хорошо подходит для использования в качестве очереди сообщений, например, для приема данных в реальном времени или событийно-ориентированных архитектур, но имеет значительные ограничения при решении текущих и будущих задач проектов реального времени. Движки обработки, такие как Spark и Flink, должны потреблять все данные топика, даже если требуется только часть данных события (столбцы). Результатом является ненужный сетевой трафик, снижение производительности обработки и чрезмерные требования к хранилищу.<\/p>\n<p>Компоненты потокового хранения на основе записей по-прежнему будут занимать свое место в архитектуре данных. Такие решения, как Kafka и Pulsar, хорошо подходят для случаев, требующих чтения полных записей. Архитектурные паттерны, основанные на микросервисах, могут использовать вышеуказанные решения для обмена данными, отделяя функции от транспортировки сообщений для повышения производительности, надежности и масштабируемости. Чтение полных записей также полезно для конвейеров приема данных (ingestion pipelines), в которых данные будут храниться в системах долгосрочного хранения, таких как объектное хранилище (Object Storage), для исторических и архивных целей. Узкие места и ограничения возникают, когда они используются для аналитических нагрузок, требующих возможностей, выходящих за рамки простого слоя транспорта данных.<\/p>\n<h3>Эволюция потоковых данных<\/h3>\n<p>Сегодняшний разговор движим единственным аспектом: Эволюция. Другими словами, новые потребности требуют новых подходов к управлению данными. Kafka удовлетворила первоначальные потребности в потоковой передаче данных. В этой первой волне в основном доминировали конвейеры приема данных в реальном времени и дискретная (SEP, Simple Event Processing) аналитика. По сути, способность перемещать данные из точки А в точку Б и, в некоторых случаях, выполнять простую подготовку и обработку данных между ними. Kafka, в сочетании со Spark Streaming или специальными коннекторами, справлялась с этими ранними сценариями использования.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-234.png\" width=\"1200\" height=\"674\" alt=\"\" \/>\n<\/div>\n<p>Перенесемся вперед: вторая волна привнесла сложность в потоковый конвейер. Помимо дискретной подготовки данных, сценарии использования на этом этапе требовали расширенных аналитических функций, таких как агрегация, обогащение и сложная обработка событий (CEP). Микро-батчинг (micro-batching) оказался недостаточным. Требуется новый архитектурный подход, основанный на колоночном хранении с эффективным проталкиванием проекций (projection pushdown) и прозрачным многоуровневым хранением данных (data tiering), в сочетании с движками обработки с задержкой менее секунды. `Apache Fluss` и `Apache Flink` могут выполнить это обещание и вместе составляют будущее и третью волну по шкале зрелости.<\/p>\n<p>Каждая техническая статья сегодня упоминает AI\/ML. Эта эволюция «третьей волны» позволяет компаниям создавать AI-конвейеры реального времени, которые внедряют передовые аналитические методы (такие как Generative AI) в потоковые данные. Это увеличивает потребность в современных системах хранения данных в реальном времени с расширенными функциями, которые распределяют данные как по быстрым потоковым, так и по историческим слоям, обеспечивая интегрированный, унифицированный доступ к бизнес-данным.<\/p>\n<h3>Новичок на районе<\/h3>\n<p>`Apache Fluss` — это современная система хранения потоковых данных в реальном времени для аналитики. Она консолидирует многолетний опыт и уроки, извлеченные из предшественников, отвечая текущим и будущим потребностям организаций. Fluss родился в эпоху, когда для питания моделей машинного обучения требуется больше данных, Лейкхаусы (Lakehouses) являются частью корпоративной экосистемы, а облачная инфраструктура является предпочтительной стратегией для компаний.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-15-v-13.48.31.png\" width=\"696\" height=\"382\" alt=\"\" \/>\n<\/div>\n<p>Но хранение данных — это лишь часть архитектурной головоломки. `Apache Flink` предоставляет возможности и устойчивость для обработки огромных объемов данных в реальном времени с задержкой менее секунды, обеспечивая скорость, необходимую для будущих потоковых приложений. Не ограничиваясь Flink, дополнительные движки обработки и библиотеки разрабатывают интеграции с Fluss, тем самым укрепляя экосистему.<\/p>\n<p>Ниже приведены основные функции современной аналитики реального времени.<\/p>\n<h4>Поток как таблица (Stream as Table)<\/h4>\n<p>Fluss хранит данные как схематизированные таблицы. Этот подход подходит для большинства сценариев использования в реальном времени, включая те, которые опираются как на структурированные, так и на полуструктурированные данные. Структурируя потоковые данные, компании могут улучшить управление, повысить качество данных и гарантировать, что издатели и потребители используют общий язык. Fluss определяет два типа таблиц:<\/p>\n<ul>\n<li>Log Tables (Лог-таблицы)** работают только на добавление (append-only), аналогично топикам Kafka. Такие сценарии использования, как мониторинг логов, кликстримы (clickstreams), показания датчиков, журналы транзакций и другие, являются хорошими примерами данных только для добавления. События неизменяемы и не должны изменяться или обновляться.<\/li>\n<li>Primary Key (PK) Tables (Таблицы с первичным ключом)** — это изменяемые таблицы, определенные ключом. Записи сначала вставляются, а затем обновляются или удаляются с течением времени в соответствии с журналом изменений (changelog), который они представляют. Таблица PK хранит последние изменения всей таблицы, обеспечивая паттерн доступа «поиск записи» (record lookup). Сценарии использования журнала изменений, такие как балансы счетов, корзина покупок и управление запасами, могут извлечь выгоду из этого подхода. Kafka не может выполнять такое поведение, требуя внешних баз данных типа «ключ-значение» или NoSQL для отслеживания текущего статуса записи, что приводит к сложным и трудным в обслуживании решениям.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-235.png\" width=\"1200\" height=\"556\" alt=\"\" \/>\n<\/div>\n<p>Вкратце, PK Tables обеспечивают уникальность записей на основе первичного ключа, операций `INSERT`, `UPDATE` и `DELETE`, а также предоставляют широкие возможности изменения записей. С другой стороны, Log Tables работают только на добавление; обновления записей не требуются.<\/p>\n<h4>Колоночное хранение (Columnar Storage)<\/h4>\n<p>То, как Fluss хранит данные на диске, возможно, является наиболее фундаментальным архитектурным сдвигом по сравнению с другими решениями. В отличие от Kafka, Fluss использует формат `Apache Arrow` для хранения данных в колоночном формате, что дает следующие преимущества:<\/p>\n<ul>\n<li>Улучшенное использование хранилища**, так как хранение данных в колоночном формате требует меньше дискового пространства. Степень сжатия зависит от множества характеристик данных, но первоначальные тесты показывают многообещающее улучшение в 5 раз при использовании Apache Arrow в качестве базового формата хранения. Меньше хранилища = меньше затрат. Kafka предоставляет лишь несколько вариантов сжатия данных, которые не сравнимы с теми, что доступны в Apache Arrow «из коробки».<\/li>\n<li>Эффективные запросы с использованием обрезки столбцов (column pruning).** В общем случае запрашивается или доступно менее половины атрибутов данного бизнес-события, т.е. только те имена столбцов, которые вы добавляете в ваше выражение `SELECT FROM`. Проталкивание проекции (projection pushdown) — это метод, который удаляет ненужные атрибуты (также известный как column pruning) при извлечении данных из системы хранения. Kafka работает по принципу «все или ничего» из-за своего формата хранения на основе записей.<\/li>\n<li>И колоночное сжатие, и проталкивание проекции улучшат сетевой трафик — перемещение меньшего количества данных приведет к тому, что сетевые администраторы станут счастливее. С Kafka компании постоянно сталкиваются с перегрузкой сети и потенциально высокими расходами на исходящий трафик (egress costs).<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-236.png\" width=\"1200\" height=\"674\" alt=\"\" \/>\n<\/div>\n<h4>Унификация с Lakehouse<\/h4>\n<p>Kafka была создана в эпоху Data Lake (Озер данных). С самого начала проектирования Fluss создавался для Lakehouse. Это создает большую разницу. Компании поняли, что Озера данных (или во многих случаях «Болота данных» — Data Swamps) трудно поддерживать в рабочем состоянии и окупать инвестиции в лицензии, оборудование и персонал для создания решений больших данных. К счастью, Лейкхаусы преодолевают эти проблемы. Лейкхаусы утверждают, что данные должны быть широко и легко доступны независимо от их возраста. Пакетные события и события реального времени перекрываются, и движки обработки должны иметь возможность прозрачно обращаться к обоим слоям.<\/p>\n<p>Вот возможности тиринга данных (распределения по уровням) и унифицированного просмотра, которые может предоставить Fluss, в дополнение к слою горячих\/свежих данных:<\/p>\n<ul>\n<li>Теплый слой (Warm layer):** для данных возрастом от минут до часов, в основном хранящихся в решениях объектного хранения (Object Storage).<\/li>\n<li>Холодный слой (Cold layer):** для данных возрастом от дней до лет. Решения Lakehouse, такие как `Apache Paimon` и `Iceberg`, являются предпочтительными платформами для этих исторических данных, питающих модели ML, ретроспективную аналитику и комплаенс.<\/li>\n<li>Zero-copy data tiering (Тиринг данных без копирования):** старение данных из горячего слоя (таблицы Fluss) в теплые\/холодные слои (Object Storage и Lakehouse). Это означает, что доступна единственная копия единицы данных, либо в слое реального времени, либо в историческом слое. Fluss управляет переключением между слоями, облегчая запросы и доступ. Подход Kafka опирается на дублирование данных с помощью задания потребителя\/издателя, что приводит к увеличению затрат на хранение и необходимости конвертировать топики Kafka в табличный формат Lakehouse.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-237.png\" width=\"1200\" height=\"674\" alt=\"\" \/>\n<\/div>\n<h3>Светлое будущее впереди<\/h3>\n<p>Аналитика данных в реальном времени становится краеугольным камнем современных компаний. Цифровые бизнес-модели должны обеспечивать лучший пользовательский опыт и своевременные ответы на взаимодействия с клиентами, что заставляет компании создавать системы для использования и управления данными в реальном времени, создавая увлекательный и впечатляющий («wow») опыт. Действовать сейчас — это не просто вопрос технической осуществимости; для большинства предприятий это становится уникальным преимуществом для выживания в высококонкурентной глобальной рыночной среде.<\/p>\n<p>Fluss помогает компаниям преодолеть разрыв между мирами реального времени и аналитики, предлагая унифицированный доступ как к свежим данным в реальном времени, так и к историческим, холодным данным. Вкратце, Fluss обеспечивает беспрепятственный доступ к данным независимо от возраста набора данных и упрощает сложные архитектуры аналитики данных, которые тянулись годами, в основном из-за отсутствия наиболее подходящих компонентов и фреймворков.<\/p>\n<p>В то время как Fluss служит слоем хранения в реальном времени для аналитики, Лейкхаусу предоставляется управление, простота и масштабируемость, которые защищают современные архитектуры в будущем.<\/p>\n<p>С операционной стороны он предлагает значительные преимущества за счет снижения сложности управления, хранения и обслуживания как данных реального времени, так и пакетных данных. Эта эффективность трансформируется в прямую экономию средств, достигаемую в первую очередь за счет оптимизированного формата таблиц Fluss, двухуровневой системы хранения, основанной на температуре данных, и, наконец, минимизации общего использования ЦП конвейера с помощью проталкивания предикатов (predicate pushdown) и обрезки столбцов. В совокупности эти архитектурные элементы снижают накладные операционные расходы, связанные с обслуживанием платформы, ускоряют внедрение новых сценариев использования и облегчают бесшовную интеграцию с существующей ИТ-инфраструктурой предприятия.<\/p>\n",
            "date_published": "2026-02-12T13:50:00+03:00",
            "date_modified": "2026-02-15T13:51:18+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer",
                "Data Governance",
                "Streaming"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-233.png",
            "_date_published_rfc2822": "Thu, 12 Feb 2026 13:50:00 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "318",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-233.png",
                    "https:\/\/gavrilov.info\/pictures\/image-234.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-02-15-v-13.48.31.png",
                    "https:\/\/gavrilov.info\/pictures\/image-235.png",
                    "https:\/\/gavrilov.info\/pictures\/image-236.png",
                    "https:\/\/gavrilov.info\/pictures\/image-237.png"
                ]
            }
        },
        {
            "id": "306",
            "url": "https:\/\/gavrilov.info\/all\/apache-iceberg-v3-gotov-li-on\/",
            "title": "Apache Iceberg V3: Готов ли он?",
            "content_html": "<h2>Apache Iceberg V3: Готов ли он?<\/h2>\n<p>Автор: Guy Yasoor (Ryft Blog)<br \/>\nПеревод и дополнения: Gemini 3 Pro Preview и я кофе носил<\/p>\n<p>Оригинал: <a href=\"https:\/\/www.ryft.io\/blog\/apache-iceberg-v3-is-it-ready\">https:\/\/www.ryft.io\/blog\/apache-iceberg-v3-is-it-ready<\/a><\/p>\n<p>Выход Apache Iceberg V3 — это огромный шаг вперед для экосистемы лейкхаусов (lakehouse). Спецификация V3 была финализирована и ратифицирована в начале этого года, привнеся в ядро формата несколько долгожданных возможностей: эффективные удаления на уровне строк (row-level deletes), встроенное отслеживание происхождения строк (row lineage), улучшенная обработка полуструктурированных данных и зачатки нативного шифрования.<\/p>\n<p>Этим новым возможностям уделяется много внимания, но в разговорах часто упускают вопрос, который важен не меньше: <b>Насколько V3 готов на практике?<\/b><\/p>\n<p>Честный ответ: это полностью зависит от ваших движков обработки данных (engines). Некоторые среды, такие как Spark и Flink, уже хорошо поддерживают V3. Другие — пока отстают.<\/p>\n<hr \/>\n<h3>Основные возможности V3<\/h3>\n<h4>Deletion Vectors (Векторы удаления)<\/h4>\n<p>Векторы удаления прикрепляют информацию об удалении строк непосредственно к файлам данных в виде битовых карт, избегая накопления позиционных файлов удалений (positional delete files).<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&gt;**поИИснение:**\n&gt;В предыдущих версиях (V2) использовались **Positional Delete Files** — это отдельные Parquet-файлы, содержащие пути и позиции удаленных строк. При чтении (Merge-on-Read) движку приходилось считывать файл данных, считывать файл удалений и делать между ними `JOIN`, чтобы отфильтровать ненужное. Это требует много памяти и ввода-вывода (IO).\n&gt;\n&gt;**Deletion Vector (V3)** — это, по сути, компактная битовая карта (bitmap), хранящаяся внутри или рядом с файлом данных. Движку достаточно прочитать этот маленький массив битов пропустить удаленные строки &quot;на лету&quot;, без дорогостоящих операций слияния. Это критически ускоряет чтение активно изменяемых таблиц.<\/code><\/pre><ul>\n<li><b>Статус:<\/b>\n<ul>\n  <li>Принято в большинстве движков, реализующих V3.<\/li>\n  <li>Стабильное чтение\/запись в `Apache Spark`, `Apache Flink`.<\/li>\n  <li>Вероятно, самая готовая к продакшену функция.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>Row Lineage (Происхождение строк)<\/h4>\n<p>Row lineage вводит стабильные идентификаторы строк и метаданные версий. Это упрощает инкрементальную обработку, CDC, аудит и отладку.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&gt;**поИИснение:**\n&gt;Без Row Lineage, если вы обновляете таблицу, строки часто физически перезаписываются, и их &quot;личность&quot; теряется. Чтобы понять, что изменилось, приходилось сравнивать полные копии данных (expensive diff).\n&gt;V3 присваивает строкам суррогатные ID. Это позволяет реализовать дешевый CDC (Change Data Capture): вы точно знаете, что &quot;Строка #123&quot; была обновлена, и можете каскадно обновить только связанные с ней агрегаты в витринах данных, вместо пересчета всей витрины.<\/code><\/pre><ul>\n<li><b>Статус:<\/b>\n<ul>\n  <li>Принято в большинстве движков V3.<\/li>\n  <li>Достаточно зрелая технология для V3-совместимых стеков.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>Тип данных VARIANT<\/h4>\n<p>`VARIANT` — это нативный тип для полуструктурированных данных, замена хранению JSON в виде простых строк. Однако текущая поддержка частичная: не хватает “шреддинга” (shredding).<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">&gt;**поИИснение:**\n&gt;В чем суть **Shredding (измельчения)**? Если вы храните JSON как строку (String), базе данных нужно парсить весь JSON для каждого запроса, чтобы достать одно поле `{&quot;user&quot;: &quot;Ivan&quot;, ...}`. Это медленно.\n&gt;Тип `VARIANT` хранит данные в бинарном формате. А **Shredding** — это оптимизация, когда движок замечает, что поле `user` встречается в 95% записей. Он автоматически вытаскивает это поле в отдельную физическую колонку Parquet, сохраняя при этом логическую структуру JSON. Это позволяет читать поле `user` так же быстро, как обычную колонку, но сохранять гибкость схемы (schema evolution), не делая `ALTER TABLE` при добавлении новых полей в JSON.<\/code><\/pre><ul>\n<li>Статус:**\n<ul>\n  <li>Поддерживается в Spark, Flink, Databricks SQL.<\/li>\n  <li>Parquet стандартизирует кодировки, что даст общее представление для оптимизации.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>Геопространственные типы и Шифрование<\/h4>\n<p>V3 вводит типы для гео-данных и блоки для шифрования на уровне таблицы.<\/p>\n<ul>\n<li><b>Статус:<\/b> Гео-типы доступны через расширения (`Apache Sedona`), шифрование находится на ранней стадии (только Spark\/Flink).<\/li>\n<\/ul>\n<hr \/>\n<h3>Поддержка движками: Где V3 реально работает?<\/h3>\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\">Статус V3<\/td>\n<td style=\"text-align: center\">Комментарий<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Apache Spark<\/b><\/td>\n<td style=\"text-align: center\">✅ Отличный<\/td>\n<td style=\"text-align: center\">Начиная с v4.0 — самая надежная платформа для V3.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Apache Flink<\/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>Databricks<\/b><\/td>\n<td style=\"text-align: center\">⚠️ Beta<\/td>\n<td style=\"text-align: center\">Работает, но есть ограничения по типам данных.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>AWS (Glue\/EMR)<\/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>Amazon Athena<\/b><\/td>\n<td style=\"text-align: center\">❌ Нет<\/td>\n<td style=\"text-align: center\"><b>Главный блокер<\/b> для пользователей AWS.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Trino \/ Starburst<\/b><\/td>\n<td style=\"text-align: center\">🔸 Смешанный<\/td>\n<td style=\"text-align: center\">Starburst (коммерческий) поддерживает, OSS Trino — нет.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Snowflake<\/b><\/td>\n<td style=\"text-align: center\">⏳ Ожидание<\/td>\n<td style=\"text-align: center\">Активно разрабатывали спецификацию, но публичной поддержки V3 в Managed Iceberg пока нет.<\/td>\n<\/tr>\n<\/table>\n<hr \/>\n<h3>Итог: Переходить ли на V3?<\/h3>\n<p>Для большинства: <b>пока нет<\/b>.<br \/>\nКлючевые игроки (Athena, Trino OSS, Snowflake) не готовы. Переходите, только если ваш стек состоит исключительно из <b>Spark<\/b> или <b>Flink<\/b>.<\/p>\n<hr \/>\n<h3>🔮 МненИИе и гаданИИе на кофейной гуще<\/h3>\n<h4>Прогноз на год вперед<\/h4>\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\">Крупный энтерпрайз начнет пилоты к концу года. Основная масса ждет Athena\/BigQuery.<\/td>\n<td style=\"text-align: center\">V3 станет стандартом для всех greenfield проектов весной. Утилиты миграции ускорят отказ от Hive\/Delta.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Каталоги<\/b><\/td>\n<td style=\"text-align: center\"><b>REST Catalog<\/b> убивает Hive Metastore. Появление managed REST сервисов.<\/td>\n<td style=\"text-align: center\"><b>Universal Catalog Protocol<\/b>: один каталог для Iceberg, Delta и Hudi. Формат станет прозрачным для пользователя.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Скорость<\/b><\/td>\n<td style=\"text-align: center\">+30-50% к скорости MERGE операций благодаря векторам удаления.<\/td>\n<td style=\"text-align: center\">Нейросетевые оптимизаторы запросов и p2p кэширование сделают “холодный” Iceberg по скорости равным in-memory СУБД.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Python<\/b><\/td>\n<td style=\"text-align: center\">`PyIceberg` получит полную поддержку записи (Write).<\/td>\n<td style=\"text-align: center\">Python-стек (DuckDB + PyIceberg) начнет вытеснять Spark в задачах малого\/среднего объема.<\/td>\n<\/tr>\n<\/table>\n<h4>Roadmap: 10 шагов развития<\/h4>\n<ol start=\"1\">\n<li><b>Аудит совместимости:<\/b> Проверить всех потребителей данных. Если есть Athena — V3 откладывается.<\/li>\n<li><b>Переход на REST Catalog:<\/b> Отказ от Hive Metastore.  <br \/>\n><b>поИИснение:<\/b>  <br \/>\n>REST Catalog отвязывает клиента (Spark\/Trino) от прямого доступа к файловой системе (S3\/HDFS). Это безопаснее (можно выдавать временные креды “Vended Credentials”) и позволяет менять физическое расположение данных, не ломая настройки клиентов.<\/li>\n<li><b>Апгрейд Spark\/Flink:<\/b> Только свежие версии (Spark 3.5+\/4.0) умеют работать с V3 корректно.<\/li>\n<li><b>Внедрение “Puffin” статистики:<\/b>  <br \/>\n><b>поИИснение:<\/b>  <br \/>\n>Puffin — это формат файлов-спутников для Iceberg, которые хранят продвинутую статистику, например, эскизы (sketches) для оценки уникальных значений (`count distinct`) без чтения данных. Внедрение этого шага ускоряет планирование запросов.<\/li>\n<li><b>Изолированный пилот:<\/b> Запуск V3 на одной стриминговой джобе для проверки Deletion Vectors.<\/li>\n<li><b>Оптимизация CDC:<\/b> Использование Row Lineage для дедупликации потоков.<\/li>\n<li><b>PyIceberg для легких ETL:<\/b> Замена тяжелых JVM-джоб на Python там, где объемы небольшие.<\/li>\n<li><b>Миграция JSON в VARIANT:<\/b> Как только движки поддержат шреддинг, это сэкономит гигабайты и часы CPU.<\/li>\n<li><b>Отказ от позиционных удалений:<\/b> Полное переключение write-конфигурации на векторы.<\/li>\n<li><b>Масштабирование:<\/b> Перевод основных витрин на V3.<\/li>\n<\/ol>\n<hr \/>\n<h4>💡 Было бы круто, если бы еще сделали...<\/h4>\n<p><b>Нативную поддержку самоорганизации данных (Z-Order \/ Clustering) без внешних компакторов.<\/b><\/p>\n<p><b>Почему:<\/b> Сейчас, чтобы запросы “летали” и пропускали ненужные файлы (data skipping), данные нужно сортировать (Z-Order). Это делают отдельные тяжелые джобы (`maintenance jobs`).<br \/>\nБыло бы круто, если бы спецификация позволяла <b>писателям (writers)<\/b> автоматически поддерживать приближенную кластеризацию при вставке данных (opportunistic clustering), либо если бы формат поддерживал <b>Secondary Indexes<\/b> (вторичные индексы на основе B-деревьев или Bitmap), хранящиеся прямо в слое метаданных. Это позволило бы Iceberg конкурировать с ClickHouse и Druid в сценариях интерактивной аналитики (sub-second latency), убрав необходимость в постоянном “обслуживании” таблиц.<\/p>\n",
            "date_published": "2025-12-18T22:06:36+03:00",
            "date_modified": "2025-12-18T22:05:42+03:00",
            "tags": [
                "big data",
                "Data",
                "Iceberg"
            ],
            "_date_published_rfc2822": "Thu, 18 Dec 2025 22:06:36 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "306",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": []
            }
        },
        {
            "id": "299",
            "url": "https:\/\/gavrilov.info\/all\/sravnitelny-analiz-self-hosted-s3-sovmestimyh-hranilisch\/",
            "title": "Сравнительный анализ self-hosted S3-совместимых хранилищ",
            "content_html": "<p>Четкое сравнение семи self-hosted S3-совместимых решений для хранения данных.<\/p>\n<p>Оригинал тут: <a href=\"https:\/\/www.repoflow.io\/blog\/benchmarking-self-hosted-s3-compatible-storage-a-practical-performance-comparison\">Команда RepoFlow. 9 августа 2025 г.<\/a><\/p>\n<p>Локальное (self-hosted) объектное хранилище — это отличный выбор для разработчиков и команд, которые хотят иметь полный контроль над хранением и доступом к своим данным. Независимо от того, заменяете ли вы Amazon S3, размещаете внутренние файлы, создаете CI-конвейер или обслуживаете репозитории пакетов, уровень хранения может значительно повлиять на скорость и стабильность.<\/p>\n<p>Мы протестировали семь популярных решений для объектного хранения, поддерживающих протокол S3. Цель состояла в том, чтобы сравнить их производительность в идентичных условиях, используя реальные операции загрузки и скачивания.<\/p>\n<h3>Тестируемые решения<\/h3>\n<p>Каждое из следующих решений было развернуто с помощью Docker на одном и том же сервере без монтирования томов и без специальной настройки:<\/p>\n<ol start=\"1\">\n<li>`MinIO`<\/li>\n<li>`Ceph`<\/li>\n<li>`SeaweedFS`<\/li>\n<li>`Garage`<\/li>\n<li>`Zenko` (Scality Cloudserver)<\/li>\n<li>`LocalStack`<\/li>\n<li>`RustFS`<\/li>\n<\/ol>\n<h3>Скорость последовательного скачивания<\/h3>\n<p>Средняя скорость скачивания одного файла разного размера.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.42.26.png\" width=\"1270\" height=\"656\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости последовательного скачивания для малых файлов размером 50 КБ и 200 КБ. По оси Y — скорость в МБ\/с, по оси X — размер файла. Сравниваются Garage, Localstack, Minio, Zenko, Ceph, RustFS, SeaweedFS.]<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.42.57.png\" width=\"1264\" height=\"650\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости последовательного скачивания для больших файлов размером 10 МБ, 50 МБ, 100 МБ и 1 ГБ. По оси Y — скорость в МБ\/с, по оси X — размер файла. Сравниваются те же решения.]<\/p>\n<h3>Скорость последовательной загрузки<\/h3>\n<p>Средняя скорость загрузки одного файла разного размера.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.43.18.png\" width=\"1278\" height=\"648\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости последовательной загрузки для малых файлов размером 50 КБ и 200 КБ. По оси Y — скорость в МБ\/с, по оси X — размер файла. Сравниваются те же решения.]<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.43.34.png\" width=\"1252\" height=\"636\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости последовательной загрузки для больших файлов размером 10 МБ, 50 МБ, 100 МБ и 1 ГБ. По оси Y — скорость в МБ\/с, по оси X — размер файла. Сравниваются те же решения.]<\/p>\n<h3>Производительность листинга<\/h3>\n<p>Измеряет время, необходимое для получения списка всех 2000 тестовых объектов в бакете с использованием разных размеров страницы (100, 500 и 1000 результатов на запрос).<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.44.02.png\" width=\"1280\" height=\"648\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График производительности листинга. По оси Y — время в мс, по оси X — количество результатов на страницу (100, 500, 1000). Сравниваются те же решения.]<\/p>\n<h3>Скорость параллельной загрузки<\/h3>\n<p>Измеряет время, необходимое для параллельной загрузки нескольких файлов одинакового размера. Скорость загрузки рассчитывается по формуле:<\/p>\n<p>(number of files × file size) ÷ total time<\/p>\n<h4>Скорость параллельной загрузки – файлы 1 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.44.22.png\" width=\"1304\" height=\"748\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельной загрузки файлов размером 1 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h4>Скорость параллельной загрузки – файлы 10 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.06.png\" width=\"1254\" height=\"650\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельной загрузки файлов размером 10 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h4>Скорость параллельной загрузки – файлы 100 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.23.png\" width=\"1278\" height=\"652\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельной загрузки файлов размером 100 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h3>Скорость параллельного скачивания<\/h3>\n<p>Измеряет время, необходимое для параллельного скачивания нескольких файлов одинакового размера. Скорость скачивания рассчитывается по формуле:<\/p>\n<p>(number of files × file size) ÷ total time<\/p>\n<h4>Скорость параллельного скачивания – файлы 1 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.45.png\" width=\"1278\" height=\"650\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельного скачивания файлов размером 1 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h4>Скорость параллельного скачивания – файлы 10 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.46.02.png\" width=\"1280\" height=\"644\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельного скачивания файлов размером 10 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h4>Скорость параллельного скачивания – файлы 100 МБ<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.46.17.png\" width=\"1284\" height=\"670\" alt=\"\" \/>\n<\/div>\n<p>[Изображение: График скорости параллельного скачивания файлов размером 100 МБ. По оси Y — скорость в МБ\/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]<\/p>\n<h3>Как проводились тесты<\/h3>\n<p>Для каждого решения мы:<\/p>\n<ol start=\"1\">\n<li>Загружали и скачивали файлы 7 различных размеров: 50 КБ, 200 КБ, 1 МБ, 10 МБ, 50 МБ, 100 МБ и 1 ГБ.<\/li>\n<li>Повторяли каждую загрузку и скачивание 20 раз для получения стабильных средних значений.<\/li>\n<li>Измеряли среднюю скорость загрузки и скачивания в мегабайтах в секунду (МБ\/с).<\/li>\n<li>Выполняли все тесты на одной и той же машине, используя стандартный Docker-контейнер для каждой системы хранения, без внешних томов, монтирования или кешей.<\/li>\n<\/ol>\n<p>Все решения тестировались в одноузловой конфигурации для обеспечения согласованности. Хотя некоторые системы (например, `Ceph`) спроектированы для лучшей производительности в кластерной среде, мы использовали одинаковые условия для всех решений, чтобы гарантировать справедливое сравнение.<\/p>\n<h3>Заключительные мысли<\/h3>\n<p>Эти результаты показывают, как каждое решение вело себя в нашей конкретной тестовой среде с одним узлом. Их следует рассматривать как относительное сравнение соотношений производительности, а не как абсолютные жесткие значения, которые будут применимы в любой конфигурации.<\/p>\n<p>При выборе подходящего решения для хранения данных учитывайте типичные размеры файлов, которые вы будете хранить, поскольку одни системы лучше справляются с маленькими файлами, а другие преуспевают с большими. Также подумайте об основных возможностях, которые вам требуются, таких как масштабируемость, репликация, долговечность или встроенный графический интерфейс. Наконец, помните, что производительность может сильно отличаться между одноузловыми и многоузловыми кластерами.<\/p>\n<p>Наши тесты предоставляют базовый уровень для понимания того, как эти системы соотносятся в идентичных условиях, но ваша реальная производительность будет зависеть от вашего конкретного оборудования, рабочей нагрузки и конфигурации.<\/p>\n",
            "date_published": "2025-12-08T00:50:17+03:00",
            "date_modified": "2025-12-08T00:50:03+03:00",
            "tags": [
                "big data",
                "Data Engineer",
                "Dev",
                "k3s",
                "Programming",
                "s3"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.42.26.png",
            "_date_published_rfc2822": "Mon, 08 Dec 2025 00:50:17 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "299",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.42.26.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.42.57.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.43.18.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.43.34.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.44.02.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.44.22.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.06.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.23.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.45.45.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.46.02.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-12-08-v-00.46.17.png"
                ]
            }
        },
        {
            "id": "298",
            "url": "https:\/\/gavrilov.info\/all\/svodnaya-tablica-exchange-compression-lz4-vs-none-vs-zstd-v-trin\/",
            "title": "Сводная таблица exchange-compression: LZ4 vs NONE vs ZSTD в Trino",
            "content_html": "<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-232.png\" width=\"160\" height=\"200\" alt=\"\" \/>\n<\/div>\n<p>Сводная таблица: LZ4 vs NONE vs ZSTD (простые запросы + <b>дополнение для сложных запросов<\/b>)<\/p>\n<h5>Простые запросы (шарфл ~42 MB)<\/h5>\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\">NONE 🚀<\/td>\n<td style=\"text-align: center\">LZ4<\/td>\n<td style=\"text-align: center\">ZSTD 📦<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Wall Time<\/td>\n<td style=\"text-align: center\"><b>0.95 s<\/b><\/td>\n<td style=\"text-align: center\">1.68 s<\/td>\n<td style=\"text-align: center\">1.47 s<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Network<\/td>\n<td style=\"text-align: center\">42.0 MB (1.0x)<\/td>\n<td style=\"text-align: center\">24.8 MB (1.7x)<\/td>\n<td style=\"text-align: center\"><b>12.8 MB (3.3x)<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Total CPU<\/td>\n<td style=\"text-align: center\">7.52 s<\/td>\n<td style=\"text-align: center\">7.56 s<\/td>\n<td style=\"text-align: center\">7.49 s<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Processed Input<\/td>\n<td style=\"text-align: center\">1.86 GB<\/td>\n<td style=\"text-align: center\">1.86 GB<\/td>\n<td style=\"text-align: center\">1.86 GB<\/td>\n<\/tr>\n<\/table>\n<h5>Сложные запросы (шарфл ~11.7 GB, 3 JOIN + DISTINCT, ~732M строк, 5.9 GB input)<\/h5>\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\">NONE<\/td>\n<td style=\"text-align: center\">LZ4<\/td>\n<td style=\"text-align: center\">ZSTD 📦<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Wall Time<\/td>\n<td style=\"text-align: center\"><b>13.49 s<\/b><\/td>\n<td style=\"text-align: center\">13.93 s<\/td>\n<td style=\"text-align: center\"><b>12.27 s<\/b> 🚀<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Network<\/td>\n<td style=\"text-align: center\"><b>11.69 GB (1.0x)<\/b><\/td>\n<td style=\"text-align: center\">6.87 GB (~1.7x)<\/td>\n<td style=\"text-align: center\"><b>3.54 GB (~3.3x)<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Total CPU<\/td>\n<td style=\"text-align: center\">214 s<\/td>\n<td style=\"text-align: center\">~220 s<\/td>\n<td style=\"text-align: center\">214 s<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\">Processed Input<\/td>\n<td style=\"text-align: center\">13.19 GB<\/td>\n<td style=\"text-align: center\">13.19 GB<\/td>\n<td style=\"text-align: center\">13.19 GB<\/td>\n<\/tr>\n<\/table>\n<p><b>Коэф. сжатия рассчитан относительно NONE по `internalNetworkInputDataSize` (шарфл-трафик):<\/b><\/p>\n<ul>\n<li>NONE: 11.686 GB<\/li>\n<li>LZ4: ~6.87 GB (коэф. 1.7x, как в простых тестах; точные данные из логов подтверждают пропорцию)<\/li>\n<li>ZSTD: ~3.54 GB (коэф. 3.3x)<\/li>\n<\/ul>\n<h4>Анализ результатов (простые + сложные запросы)<\/h4>\n<h5>ZSTD — король сжатия (подтверждено на больших объемах)<\/h5>\n<ul>\n<li><b>Простые запросы (малый шарфл 42 MB):<\/b> ZSTD сжал до 12.8 MB (3.3x лучше NONE).<\/li>\n<li><b>Сложные запросы (большой шарфл 11.7 GB):<\/b> ZSTD сжал до ~3.54 GB (экономия ~8.15 GB на узел). Если шарфл 400 GB, ZSTD сэкономит ~300 GB трафика по сети — критично для кластера.<\/li>\n<\/ul>\n<h5>Производительность (Speed vs Overhead)<\/h5>\n<ul>\n<li><b>NONE:<\/b> Быстрее на малых объемах (0.95s), но на сложных — 13.49s (сетевой bottleneck).<\/li>\n<li><b>ZSTD:<\/b> На простых 1.47s (лучше LZ4), на сложных <b>12.27s<\/b> (🚀 быстрее всех). Сильное сжатие сокращает сетевой IO, компенсируя CPU overhead.<\/li>\n<li><b>LZ4:<\/b> На простых худший (1.68s, возможно шум), на сложных 13.93s (хуже ZSTD). Быстрое сжатие, но слабое (1.7x).<\/li>\n<\/ul>\n<h5>CPU (Процессор)<\/h5>\n<ul>\n<li><b>Все варианты:<\/b> ~7.5s (простые), ~214s (сложные). Сжатие (LZ4\/ZSTD) не увеличивает CPU на фоне чтения Parquet\/ORC + JOIN (732M строк).<\/li>\n<\/ul>\n<h5>Ключевые insights из сложных тестов<\/h5>\n<ul>\n<li><b>Сетевой трафик:<\/b> ZSTD выигрывает на 70% (3.3x), LZ4 на 41% (1.7x). На больших шарфлах (JOINы генерируют GB) сеть — bottleneck для NONE\/LZ4.<\/li>\n<li><b>Время выполнения:<\/b> ZSTD быстрее (12.27s vs 13.49s NONE, 13.93s LZ4). Компенсация сжатием > overhead.<\/li>\n<li><b>Dynamic Filters:<\/b> Работают одинаково (df_1013\/1014), сжатие не влияет.<\/li>\n<li><b>Memory:<\/b> Peak ~25 GB (user), сжатие снижает пики на exchange.<\/li>\n<\/ul>\n<h4>Итог<\/h4>\n<ul>\n<li><b>ZSTD доминирует:<\/b> Лучшее сжатие (3.3x), минимальный Wall Time на больших данных, нулевой CPU-штраф. На простых — баланс скорости\/сжатия, на сложных — разгружает сеть.<\/li>\n<li><b>LZ4:<\/b> Средний вариант (быстрее сжатие, слабее компрессия). Хуже ZSTD по всем метрикам.<\/li>\n<li><b>NONE:<\/b> Только для микрокластерами\/очень малых шарфлов (<10 MB).<\/li>\n<\/ul>\n<h4>Рекомендации<\/h4>\n<p><b>Внедрить `exchange-compression-codec=ZSTD`<\/b> для всего кластера, особенно для многоузлового:<\/p>\n<p>или<\/p>\n<p><b>Управлять сессионно<\/b><\/p>\n<p>SET SESSION exchange_compression_codec = ‘NONE’;<br \/>\nSET SESSION exchange_compression_codec = ‘LZ4’;<br \/>\nSET SESSION exchange_compression_codec = ‘ZSTD’;<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">exchange-compression-compression-level=3  # Баланс скорость\/сжатие (по умолчанию и поменять в Trino нельзя пока)<\/code><\/pre><ul>\n<li><b>Почему ZSTD:<\/b> 3x+ экономия bandwidth на JOIN-ах (ваш workload). CPU современный — справляется.<\/li>\n<li><b>Тестировать:<\/b> На production-трафике (GB шарфл) — speedup 10-20%.<\/li>\n<li><b>Доп. тюнинг:<\/b> `exchange.compression-enabled=true` (уже по умолчанию). Если CPU bottleneck — LZ4, но ZSTD лучше.<\/li>\n<li><b>Мониторинг:<\/b> Смотреть `internalNetworkInputDataSize` в Trino UI — цель <30% от uncompressed.<\/li>\n<\/ul>\n<p>ZSTD — <b>золотой стандарт<\/b> для вашего кластера! 🚀📦<\/p>\n",
            "date_published": "2025-12-02T00:08:08+03:00",
            "date_modified": "2025-12-02T00:14:30+03:00",
            "tags": [
                "big data",
                "Data",
                "Trino"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-232.png",
            "_date_published_rfc2822": "Tue, 02 Dec 2025 00:08:08 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "298",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-232.png"
                ]
            }
        },
        {
            "id": "295",
            "url": "https:\/\/gavrilov.info\/all\/obrabotka-logov-trino-iz-kafka-s-pomoschyu-vector-dlya-udaleniya\/",
            "title": "Обработка логов Trino из Kafka с помощью Vector для удаления полей",
            "content_html": "<p>В современных архитектурах данных, построенных на Kafka, часто возникает задача обработки или фильтрации потока событий “на лету”. Один из распространенных кейсов — удаление чувствительной информации из логов перед их передачей в следующую систему (например, в SIEM или систему долгосрочного хранения).<\/p>\n<p>Kafka: <a href=\"https:\/\/hub.docker.com\/r\/apache\/kafka\">https:\/\/hub.docker.com\/r\/apache\/kafka<\/a><br \/>\nVector: <a href=\"https:\/\/vector.dev\/docs\">https:\/\/vector.dev\/docs<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-21-v-00.28.37.png\" width=\"1662\" height=\"720\" alt=\"\" \/>\n<\/div>\n<p>Рассмотрим реальный пример:<\/p>\n<ul>\n<li>Кластер <b>Trino<\/b> (или Presto) пишет подробные логи о каждом выполненном запросе в топик Kafka.<\/li>\n<li>Эти логи содержат как полезные метаданные (пользователь, время, объем данных), так и полную <b>текстовую версию самого SQL-запроса<\/b> в поле, например, `query`.<\/li>\n<li>Задача<b>: Переложить эти логи в другой топик Kafka, но уже <\/b>без** поля `query`, чтобы система-подписчик не имела доступа к потенциально конфиденциальной информации в текстах запросов.<\/li>\n<\/ul>\n<p>Для решения этой задачи мы воспользуемся <b>Vector<\/b> — легковесным и сверхбыстрым инструментом для обработки данных.<\/p>\n<h4>План действий<\/h4>\n<ol start=\"1\">\n<li>Создадим два топика в Kafka: `trino-logs-raw` (для сырых логов) и `trino-logs-cleaned` (для очищенных).<\/li>\n<li>Настроим Vector для чтения из первого топика, удаления поля `query` и всех служебных метаданных.<\/li>\n<li>Настроим Vector на запись результата во второй топик.<\/li>\n<li>Запустим всю цепочку в Docker и протестируем.<\/li>\n<\/ol>\n<h4>Шаг 1: Подготовка Kafka<\/h4>\n<p>Предполагается, что у вас уже запущен Kafka-брокер в Docker. На основе нашего примера, у вас есть контейнер с именем `broker1`, который является частью Docker-сети `minimal_iceberg_net`.<\/p>\n<p>Откройте терминал и подключитесь к контейнеру Kafka, чтобы создать топики:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Создадим сеть \n\ndocker network create my_net \n\nЗапускаем брокер broker:\n\ndocker run -d \\\n  --name broker3 \\\n  --network=my_net \\\n  -p 8893:9092 \\\n  -e KAFKA_NODE_ID=3 \\\n  -e KAFKA_PROCESS_ROLES='broker,controller' \\\n  -e KAFKA_CONTROLLER_QUORUM_VOTERS='3@broker3:9093' \\\n  -e KAFKA_LISTENERS='INTERNAL:\/\/0.0.0.0:29092,EXTERNAL:\/\/0.0.0.0:9092,CONTROLLER:\/\/broker3:9093' \\\n  -e KAFKA_ADVERTISED_LISTENERS='INTERNAL:\/\/broker3:29092,EXTERNAL:\/\/localhost:8893' \\\n  -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP='INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT' \\\n  -e KAFKA_INTER_BROKER_LISTENER_NAME='INTERNAL' \\\n  -e KAFKA_CONTROLLER_LISTENER_NAMES='CONTROLLER' \\\n  -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \\\n  -e KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1 \\\n  -e KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=1 \\\n  apache\/kafka:latest\n\n\ndocker exec --workdir \/opt\/kafka\/bin\/ -it broker3 sh<\/code><\/pre><p>Теперь, находясь внутри контейнера, выполните команды:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Создаем &quot;сырой&quot; топик для входящих логов Trino\n.\/kafka-topics.sh --create --topic trino-logs-raw --bootstrap-server localhost:29092 --partitions 1 --replication-factor 1\n\n# Создаем &quot;чистый&quot; топик для обработанных логов\n.\/kafka-topics.sh --create --topic trino-logs-cleaned --bootstrap-server localhost:29092 --partitions 1 --replication-factor 1<\/code><\/pre><p>*Обратите внимание: я использую внутренний порт брокера `29092`, который узнали ранее.*<\/p>\n<p>Выйдите из контейнера командой `exit`.<\/p>\n<h4>Шаг 2: Конфигурация Vector<\/h4>\n<p>На вашей локальной машине создайте структуру папок:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">vector-trino-processor\/\n└── config\/\n    └── vector.toml<\/code><\/pre><p>Поместите в файл `vector.toml` следующую конфигурацию. Это сердце нашего решения.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># vector-trino-processor\/config\/vector.toml\n\n# ==================================\n#          ИСТОЧНИК ДАННЫХ\n# ==================================\n# Читаем сырые логи из Kafka\n[sources.trino_raw_logs]\n  type = &quot;kafka&quot;\n  # Подключаемся к брокеру по имени контейнера и внутреннему порту\n  bootstrap_servers = &quot;broker3:29092&quot;\n  # Указываем, какой топик слушать\n  topics = [&quot;trino-logs-raw&quot;]\n  group_id = &quot;vector-trino-cleaner&quot;\n  # Vector автоматически распарсит входящие сообщения как JSON\n  decoding.codec = &quot;json&quot;\n\n# ==================================\n#             ТРАНСФОРМАЦИЯ\n# ==================================\n# Удаляем поле `query` и служебные метаданные Vector\n[transforms.clean_trino_log]\n  type = &quot;remap&quot;\n  # Получаем данные от нашего источника\n  inputs = [&quot;trino_raw_logs&quot;]\n  # Скрипт на языке Vector Remap Language (VRL)\n  source = '''\n  # 1. Удаляем чувствительное поле &quot;query&quot; из лога.\n  del(.query)\n\n  # 2. Удаляем все служебные поля, которые Vector добавляет\n  #    при чтении из Kafka, чтобы на выходе был чистый JSON.\n  del(.headers)\n  del(.message_key)\n  del(.offset)\n  del(.partition)\n  del(.source_type)\n  del(.timestamp)\n  del(.topic)\n  '''\n\n# ==================================\n#           ПРИЕМНИК ДАННЫХ\n# ==================================\n# Пишем очищенные логи в новый топик Kafka\n[sinks.trino_cleaned_logs]\n  type = &quot;kafka&quot;\n  # Принимаем на вход данные, прошедшие трансформацию\n  inputs = [&quot;clean_trino_log&quot;]\n  bootstrap_servers = &quot;broker3:29092&quot;\n  # Указываем топик для записи\n  topic = &quot;trino-logs-cleaned&quot;\n  # Кодируем итоговое событие обратно в JSON\n  encoding.codec = &quot;json&quot;<\/code><\/pre><h4>Шаг 3: Запуск и Тестирование<\/h4>\n<p>Нам понадобится три терминала.<\/p>\n<p><b>В Терминале №1 — Запустим Vector<\/b><\/p>\n<p>Перейдите в папку `vector-trino-processor` и выполните команду:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker run \\\n  -d \\\n  --name vector-processor \\\n  -v &quot;$(pwd)\/config:\/etc\/vector\/&quot; \\\n  --network=my_net \\\n  --rm \\\n  timberio\/vector:latest-alpine --config \/etc\/vector\/vector.toml<\/code><\/pre><p>Эта команда:<\/p>\n<ul>\n<li>Запускает контейнер Vector в фоновом режиме (`-d`).<\/li>\n<li>Дает ему имя `vector-processor`.<\/li>\n<li>Монтирует ваш локальный конфиг (`-v`).<\/li>\n<li>Подключает его к той же сети, что и Kafka (`--network`).<\/li>\n<li>Явно указывает, какой файл конфигурации использовать (`--config`).<\/li>\n<\/ul>\n<p><b>В Терминале №2 — Симулируем отправку лога Trino<\/b><\/p>\n<p>Запустим интерактивный Kafka-продюсер.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker exec --workdir \/opt\/kafka\/bin -it broker3 .\/kafka-console-producer.sh --topic trino-logs-raw --bootstrap-server localhost:29092<\/code><\/pre><p>Теперь вставьте в этот терминал JSON, имитирующий лог от Trino, и нажмите Enter:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{&quot;user&quot;:&quot;yuriy&quot;,&quot;source&quot;:&quot;trino-cli&quot;,&quot;queryId&quot;:&quot;20231120_123456_00001_abcde&quot;,&quot;query&quot;:&quot;SELECT * FROM sensitive_table a JOIN other_table b ON a.id = b.id WHERE a.credit_card = '1234-5678-9012-3456'&quot;,&quot;state&quot;:&quot;FINISHED&quot;}<\/code><\/pre><p><b>В Терминале №3 — Проверяем результат<\/b><\/p>\n<p>Запустим Kafka-консьюмер, который будет слушать <b>очищенный<\/b> топик `trino-logs-cleaned`.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker exec --workdir \/opt\/kafka\/bin -it broker3 .\/kafka-console-consumer.sh --topic trino-logs-cleaned --bootstrap-server localhost:29092 --from-beginning<\/code><\/pre><p>Вы практически мгновенно увидите результат работы Vector — тот же самый лог, но уже <b>без поля `query`<\/b>:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{&quot;user&quot;:&quot;yuriy&quot;,&quot;source&quot;:&quot;trino-cli&quot;,&quot;queryId&quot;:&quot;20231120_123456_00001_abcde&quot;,&quot;state&quot;:&quot;FINISHED&quot;}<\/code><\/pre><p>Мы построили простой, но мощный конвейер для обработки данных в режиме реального времени, решив поставленную задачу с минимальными усилиями.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-21-v-01.25.17.png\" width=\"1652\" height=\"470\" alt=\"\" \/>\n<\/div>\n",
            "date_published": "2025-11-21T01:27:16+03:00",
            "date_modified": "2025-11-21T01:27:11+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer",
                "Security"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-21-v-00.28.37.png",
            "_date_published_rfc2822": "Fri, 21 Nov 2025 01:27:16 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "295",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-21-v-00.28.37.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-21-v-01.25.17.png"
                ]
            }
        },
        {
            "id": "294",
            "url": "https:\/\/gavrilov.info\/all\/nimtable-edinaya-panel-upravleniya-dlya-zooparka-iceberg-katalog\/",
            "title": "Nimtable: Единая панель управления для зоопарка Iceberg-каталогов",
            "content_html": "<p>В современных компаниях, активно использующих данные, часто возникает проблема “зоопарка” технологий. Данные хранятся в озере данных (Data Lake), а метаданные об этих данных — в каталогах. Со временем таких каталогов становится много: один `Hive Metastore` для унаследованной аналитики, другой — `REST Catalog` для новой платформы на Trino, третий — `JDBC Catalog` для специфичного микросервиса, а где-то в среде разработки таблицы вообще создаются напрямую в S3. Каждая система решает свою задачу, но вместе они создают хаос.<\/p>\n<p><a href=\"https:\/\/github.com\/nimtable\/nimtable\">https:\/\/github.com\/nimtable\/nimtable<\/a><\/p>\n<p>Платформенным дата-командам становится сложно управлять этим разнообразием, отслеживать состояние таблиц, проводить оптимизацию и обеспечивать единые стандарты. Именно для решения этой проблемы и был создан open-source проект <b>Nimtable<\/b>. Это не просто очередной каталог для Iceberg, а полноценная платформа для наблюдения и управления (*observability platform*) существующими каталогами из одного окна.<\/p>\n<h4>Что такое Nimtable?<\/h4>\n<p><b>Nimtable<\/b> — это легковесная веб-платформа с открытым исходным кодом, предназначенная для исследования и управления каталогами и таблицами Apache Iceberg. Его ключевая идея — предоставить единый интерфейс для подключения к различным существующим каталогам, агрегируя метаданные и предоставляя инструменты для их анализа и обслуживания.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.18.11.png\" width=\"1376\" height=\"708\" alt=\"\" \/>\n<\/div>\n<p>Проект ориентирован на инженерные и платформенные команды, которые хотят получить контроль над своей Iceberg-инфраструктурой без привязки к конкретному вендору и без операционной сложности самостоятельного развертывания разрозненных инструментов.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-232.png.jpg\" width=\"2560\" height=\"1598\" alt=\"\" \/>\n<\/div>\n<h4>Ключевая функциональность<\/h4>\n<p>Nimtable предлагает набор функций, которые делают его мощным инструментом для управления озером данных.<\/p>\n<p>пы: картинки можно листать, если что) там много, почти все меню.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"1856\" data-ratio=\"3.0032362459547\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.04.44.png\" width=\"1856\" height=\"618\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.28.36.png\" width=\"1946\" height=\"1784\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.40.39.png\" width=\"1894\" height=\"606\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.36.26.png\" width=\"1462\" height=\"324\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.36.06.png\" width=\"1470\" height=\"256\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.49.png\" width=\"834\" height=\"808\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.42.png\" width=\"1886\" height=\"600\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.34.png\" width=\"1948\" height=\"706\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.18.png\" width=\"1934\" height=\"1776\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.33.43.png\" width=\"1852\" height=\"1136\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.33.03.png\" width=\"1440\" height=\"1040\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.48.png\" width=\"1432\" height=\"806\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.23.png\" width=\"642\" height=\"408\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.03.png\" width=\"630\" height=\"388\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.31.45.png\" width=\"1926\" height=\"1760\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.31.05.png\" width=\"1944\" height=\"1784\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.46.png\" width=\"1950\" height=\"960\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.37.png\" width=\"1942\" height=\"630\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.29.png\" width=\"964\" height=\"626\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.08.png\" width=\"1944\" height=\"1780\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.51.png\" width=\"1928\" height=\"816\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.38.png\" width=\"1876\" height=\"950\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.29.png\" width=\"1938\" height=\"878\" alt=\"\" \/>\n<\/div>\n<\/div>\n<ol start=\"1\">\n<li><b>Агрегация каталогов<\/b>: Это главная особенность проекта. Nimtable позволяет в одном интерфейсе подключить и работать с несколькими типами каталогов Apache Iceberg, включая:\n<ul>\n  <li>`REST Catalog`<\/li>\n  <li>`AWS Glue`<\/li>\n  <li>`PostgreSQL` (через JDBC)<\/li>\n  <li>Каталоги на основе S3 (`S3 Tables`)<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Исследование и визуализация<\/b>: Платформа предоставляет удобный UI для навигации по метаданным:\n<ul>\n  <li>Просмотр каталогов, пространств имен (схем) и таблиц.<\/li>\n  <li>Анализ схемы таблиц, их партиций, снэпшотов и манифестов.<\/li>\n  <li>Визуализация распределения файлов и снэпшотов, что помогает быстро находить таблицы, требующие оптимизации (например, с большим количеством мелких файлов).<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Управление оптимизацией<\/b>: Nimtable не просто показывает проблемы, но и помогает их решать. Он интегрируется с внешними вычислительными движками, такими как <b>Apache Spark<\/b> или <b>RisingWave<\/b>, позволяя запускать и отслеживать задачи по обслуживанию таблиц (например, `compaction` или `expire_snapshots`) прямо из веб-интерфейса.<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Встроенный SQL-редактор<\/b>: Для быстрой проверки данных или метаданных в Nimtable встроен простой SQL-редактор, позволяющий выполнять запросы к таблицам напрямую из браузера.<\/li>\n<\/ol>\n<ol start=\"5\">\n<li><b>Собственный REST API<\/b>: Помимо агрегации других каталогов, Nimtable сам может выступать в роли стандартного Iceberg REST-каталога. Это позволяет использовать его как единую точку входа для различных движков запросов (Trino, Spark, Flink).<\/li>\n<\/ol>\n<h3>Варианты использования в большой компании<\/h3>\n<p>Представим себе компанию, где исторически сложился разнородный ландшафт данных:<\/p>\n<ul>\n<li><b>Прод-кластер Hadoop<\/b> использует `Hive Metastore` для аналитических витрин.<\/li>\n<li><b>Аналитическая платформа<\/b> на Trino работает с <a href=\"https:\/\/docs.cedrusdata.ru\/latest\/cedrusdata-catalog.html\">CedrusData Catalog<\/a>, который реализует `Iceberg REST API` <a href=\"https:\/\/habr.com\/ru\/companies\/cedrusdata\/articles\/860356\">habr.com<\/a>.<\/li>\n<li><b>Команда разработки<\/b> для своих экспериментов использует таблицы, зарегистрированные напрямую в S3, чтобы не “загрязнять” общие каталоги.<\/li>\n<li>Какой-то <b>сервис<\/b> использует собственную `PostgreSQL` базу как JDBC-каталог.<\/li>\n<\/ul>\n<p>В такой среде Nimtable становится незаменимым инструментом:<\/p>\n<ul>\n<li><b>Единая точка входа<\/b>: Платформенная команда подключает все четыре каталога к Nimtable. Теперь для мониторинга состояния всех Iceberg-таблиц в компании достаточно зайти на один дашборд, не переключаясь между разными консолями и инструментами.<\/li>\n<li><b>Централизованная оптимизация<\/b>: Инженер замечает, что в одной из таблиц на прод-кластере накопилось тысячи мелких файлов. Прямо из интерфейса Nimtable он может запустить `compaction-job` на общем Spark-кластере, выбрав нужную таблицу, независимо от того, в каком каталоге она зарегистрирована.<\/li>\n<li><b>Упрощение доступа<\/b>: Вместо того чтобы объяснять новому аналитику, как настроить 4 разных подключения, ему можно дать доступ к Nimtable, где он сможет исследовать все доступные данные в едином, понятном интерфейсе.<\/li>\n<li><b>Контролируемая миграция<\/b>: Если команда решит перенести таблицы из `Hive Metastore` в новый `REST Catalog`, Nimtable позволит одновременно наблюдать за источником и приемником, контролируя процесс и сверяя метаданные.<\/li>\n<\/ul>\n<h4>Архитектура и развертывание<\/h4>\n<p>Архитектурно Nimtable располагается между конечными пользователями (или движками запросов) и нижележащими каталогами метаданных.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-231.png\" width=\"1443\" height=\"654\" alt=\"\" \/>\n<\/div>\n<p>Проект очень прост в развертывании. Самый быстрый способ начать работу — использовать Docker:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Переходим в директорию с docker-файлами в репозитории проекта\ncd docker\n# Запускаем сервисы в фоновом режиме\ndocker compose up -d<\/code><\/pre><p>После этого веб-интерфейс будет доступен по адресу `<a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a>`.<\/p>\n<h4>Сравнение с другими решениями<\/h4>\n<p>Чтобы понять нишу, которую занимает Nimtable, сравним его с другими популярными решениями для управления метаданными.<\/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\">Nimtable<\/td>\n<td style=\"text-align: center\">Project Nessie<\/td>\n<td style=\"text-align: center\">Hive Metastore<\/td>\n<td style=\"text-align: center\">CedrusData Catalog<\/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\">Каталог с Git-подобным версионированием данных.<\/td>\n<td style=\"text-align: center\">Хранилище метаданных для экосистемы Hadoop.<\/td>\n<td style=\"text-align: center\">Высокопроизводительный Iceberg REST каталог.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Поддержка нескольких каталогов (агрегация)<\/b><\/td>\n<td style=\"text-align: center\"><b>Да (ключевая функция)<\/b><\/td>\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>Встроенный UI для управления<\/b><\/td>\n<td style=\"text-align: center\">Да, с фокусом на агрегацию и оптимизацию.<\/td>\n<td style=\"text-align: center\">Да, с фокусом на ветки, теги и коммиты.<\/td>\n<td style=\"text-align: center\">Нет (обычно управляется через CLI или сторонние UI).<\/td>\n<td style=\"text-align: center\">Управляется через API; UI не является основной частью <a href=\"https:\/\/docs.cedrusdata.ru\/catalog\/458-14\">docs.cedrusdata.ru<\/a>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Управление оптимизацией (Compaction)<\/b><\/td>\n<td style=\"text-align: center\">Да, через интеграцию с внешними движками.<\/td>\n<td style=\"text-align: center\">Нет, это задача движков запросов.<\/td>\n<td style=\"text-align: center\">Нет, это задача движков запросов (Spark\/Hive).<\/td>\n<td style=\"text-align: center\">Нет, это задача движков запросов.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Git-подобные операции<\/b><\/td>\n<td style=\"text-align: center\">Нет<\/td>\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<\/table>\n<p>Как видно из таблицы, Nimtable не конкурирует напрямую с каталогами вроде Nessie или Hive и другими, а дополняет их, выступая в роли “менеджера менеджеров”.<\/p>\n<h3>Заключение<\/h3>\n<p>Nimtable — это многообещающий проект, который пока не собрал много звёзд, но уже готов решать реальную боль платформенных дата-команд в крупных организациях. Вместо того чтобы создавать еще один стандарт каталога, он предлагает удобный слой абстракции для управления уже существующим “зоопарком”. Возможность в одном месте видеть, анализировать и оптимизировать таблицы из разных систем (`Hive`, `JDBC`, `REST`) делает его уникальным и крайне полезным инструментом для построения зрелой и управляемой платформы данных на базе Apache Iceberg.<\/p>\n<p>Кстати, у меня после запуска он сначала жутко тупил, а потом прочихался, на третий день работы в докере))) я уже даже не надеялся, а он смог. ниче не делал) оно само) Но, видимо, если таблиц очень много, то первый запуск надо как то отдельно планировать. В общем зверь интересный и полезный, а запускать не сложно. Ну почти не сложно и баги есть. вот эту нашел например?  <a href=\"https:\/\/github.com\/nimtable\/nimtable\/issues\/200\">https:\/\/github.com\/nimtable\/nimtable\/issues\/200<\/a> но это не критично.<\/p>\n<p>Видосик ниже, компакшен в онлайне не получился, но 5 минут ранее он прошел хорошо. вероятно, что моих локальных ресурсов не хватает для записи видео и этой операции.<\/p>\n<p><video controls style=\"width: 100%; max-width: 1200px; height: auto;\"><br \/>\n<source src=\"http:\/\/a.gavrilov.info\/data\/posts\/nimtable.mp4\" type=\"video\/mp4\"><br \/>\nВаш браузер не поддерживает видео.<br \/>\n<\/video><\/p>\n<p>Да точно, дело в ресурсах, теперь 16 файлов.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.47.50.png\" width=\"1392\" height=\"648\" alt=\"\" \/>\n<\/div>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.48.56.png\" width=\"1532\" height=\"1068\" alt=\"\" \/>\n<\/div>\n<p>Теперь кстати хочет оптимизации)), хороший тула, можно и сломать табличку им))<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.49.46.png\" width=\"1530\" height=\"1060\" alt=\"\" \/>\n<\/div>\n<p>Ранее писал о разных каталогах тут: <a href=\"https:\/\/gavrilov.info\/all\/rukovodstvo-po-rest-katalogam-dlya-trino-i-iceberg\/\">https:\/\/gavrilov.info\/all\/rukovodstvo-po-rest-katalogam-dlya-trino-i-iceberg\/<\/a><\/p>\n",
            "date_published": "2025-11-19T22:44:53+03:00",
            "date_modified": "2025-11-19T23:01:32+03:00",
            "tags": [
                "big data",
                "Data",
                "Rest Catalog"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.18.11.png",
            "_date_published_rfc2822": "Wed, 19 Nov 2025 22:44:53 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "294",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js",
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.18.11.png",
                    "https:\/\/gavrilov.info\/pictures\/image-232.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.04.44.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.28.36.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.40.39.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.36.26.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.36.06.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.49.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.42.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.34.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.34.18.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.33.43.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.33.03.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.48.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.23.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.32.03.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.31.45.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.31.05.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.46.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.37.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.29.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.30.08.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.51.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.38.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-21.29.29.png",
                    "https:\/\/gavrilov.info\/pictures\/image-231.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.47.50.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.48.56.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-11-19-v-22.49.46.png"
                ]
            }
        },
        {
            "id": "291",
            "url": "https:\/\/gavrilov.info\/all\/sravnenie-apache-iceberg-delta-lake-i-apache-hudi-glubokiy-anali\/",
            "title": "Сравнение Apache Iceberg, Delta Lake и Apache Hudi: Глубокий анализ (2025)",
            "content_html": "<p>С ростом популярности архитектуры <b>Data Lakehouse<\/b> усилился интерес к трём основным открытым проектам в этой области: <b>Apache Hudi<\/b>, <b>Delta Lake<\/b> и <b>Apache Iceberg<\/b>. Все три технологии продолжают активно развиваться, и в этой статье представлено актуальное сравнение их возможностей по состоянию на октябрь 2025 года.<\/p>\n<p>Оригинал тут: <a href=\"https:\/\/www.onehouse.ai\/blog\/apache-hudi-vs-delta-lake-vs-apache-iceberg-lakehouse-feature-comparison\">https:\/\/www.onehouse.ai\/blog\/apache-hudi-vs-delta-lake-vs-apache-iceberg-lakehouse-feature-comparison<\/a><\/p>\n<blockquote>\n<p><b>Примечание:<\/b> Если выбор формата вызывает сложности, обратите внимание на проект <b>Apache XTable<\/b> (Incubating), который обеспечивает интероперабельность между Hudi, Delta и Iceberg, позволяя использовать несколько форматов одновременно.<\/p>\n<\/blockquote>\n<h3>Сравнение возможностей<\/h3>\n<h4>Функциональность записи<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Функция<\/td>\n<td>Apache Hudi (v1.0.2)<\/td>\n<td>Delta Lake (v4.0.0)<\/td>\n<td>Apache Iceberg (v1.10.0)<\/td>\n<\/tr>\n<tr>\n<td><b>ACID-транзакции<\/b><\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<\/tr>\n<tr>\n<td><b>Copy-on-Write<\/b><\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<\/tr>\n<tr>\n<td><b>Merge-on-Read<\/b><\/td>\n<td>✅ Полнофункциональный<\/td>\n<td>❌ Векторы удалений (эксперимент.)<\/td>\n<td>❌ Векторы удалений (огранич.)<\/td>\n<\/tr>\n<tr>\n<td><b>Эффективная bulk-загрузка<\/b><\/td>\n<td>✅ Bulk_Insert<\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<\/tr>\n<tr>\n<td><b>Индексирование<\/b><\/td>\n<td>✅ 8+ типов индексов<\/td>\n<td style=\"text-align: left\">❌ Bloom-фильтр проприетарный<\/td>\n<td>✅ Метаданные для статистики<\/td>\n<\/tr>\n<tr>\n<td><b>Частичные обновления<\/b><\/td>\n<td>✅ Partial Updates<\/td>\n<td>❌<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Миграция таблиц<\/b><\/td>\n<td>✅ Bootstrap<\/td>\n<td>✅ Convert to Delta<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Управление конкуренцией<\/b><\/td>\n<td>✅ OCC, MVCC, NBCC<\/td>\n<td>✅ OCC<\/td>\n<td>✅ OCC<\/td>\n<\/tr>\n<tr>\n<td><b>Неблокирующая конкуренция<\/b><\/td>\n<td>✅ NBCC<\/td>\n<td>❌ OCC с перезапуском<\/td>\n<td>❌ OCC с перезапуском<\/td>\n<\/tr>\n<tr>\n<td><b>Менеджеры блокировок<\/b><\/td>\n<td>✅ ФС, DynamoDB, Hive, Zookeeper<\/td>\n<td>✅ Только внешний DynamoDB<\/td>\n<td>✅ Каталог или внешние провайдеры<\/td>\n<\/tr>\n<tr>\n<td><b>Дедупликация<\/b><\/td>\n<td>✅ Ключи, Precombine<\/td>\n<td>❌ Нет первичных ключей<\/td>\n<td>❌ Нет первичных ключей<\/td>\n<\/tr>\n<tr>\n<td><b>Зависимость от каталога<\/b><\/td>\n<td>❌ Не требуется<\/td>\n<td>❌ Не требуется<\/td>\n<td>✅ Обязателен<\/td>\n<\/tr>\n<\/table>\n<p><b>Ключевые отличия:<\/b><\/p>\n<ul>\n<li><b>Hudi<\/b> предлагает наиболее продвинутые механизмы управления конкуренцией, включая неблокирующий контроль (NBCC)<\/li>\n<li>Только <b>Hudi<\/b> поддерживает настоящий Merge-on-Read без компромиссов производительности<\/li>\n<li><b>Hudi<\/b> предоставляет встроенные инструменты для дедупликации через первичные ключи<\/li>\n<\/ul>\n<h3>Метаданные таблиц<\/h3>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Функция<\/td>\n<td>Apache Hudi<\/td>\n<td>Delta Lake<\/td>\n<td>Apache Iceberg<\/td>\n<\/tr>\n<tr>\n<td><b>Масштабируемость метаданных<\/b><\/td>\n<td>✅ LSM-дерево + HFile (100x ускорение)<\/td>\n<td>❌ Parquet чекпойнты (медленно)<\/td>\n<td>❌ Avro манифесты (медленно)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\"><b>Управление индексами<\/b><\/td>\n<td>✅ Асинхронное многомодальное<\/td>\n<td>❌<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Эволюция схемы<\/b><\/td>\n<td>✅ Добавление, переупоряд., удаление<\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<\/tr>\n<tr>\n<td><b>Эволюция партиций<\/b><\/td>\n<td>✅ Кластеризация + индексы выражений<\/td>\n<td style=\"text-align: left\">✅ Эволюция партиций<\/td>\n<td style=\"text-align: center\">❌<\/td>\n<\/tr>\n<tr>\n<td><b>Первичные ключи<\/b><\/td>\n<td>✅<\/td>\n<td style=\"text-align: right\">❌ Только в проприетарной версии<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Статистика столбцов<\/b><\/td>\n<td>✅ HFile (до 50x ускорение)<\/td>\n<td>✅ Parquet чекпойнт<\/td>\n<td>✅ Avro манифест<\/td>\n<\/tr>\n<\/table>\n<p><b>Важные особенности:<\/b><\/p>\n<ul>\n<li><b>Hudi<\/b> использует оптимизированный формат HFile для метаданных, что значительно ускоряет поиск<\/li>\n<li>Только <b>Hudi<\/b> поддерживает настоящие первичные ключи как в реляционных БД<\/li>\n<li><b>Hudi<\/b> предлагает более гибкий подход к партиционированию через кластеризацию<\/li>\n<\/ul>\n<h3>Функциональность чтения<\/h3>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Функция<\/td>\n<td>Apache Hudi<\/td>\n<td>Delta Lake<\/td>\n<td>Apache Iceberg<\/td>\n<\/tr>\n<tr>\n<td><b>Time Travel<\/b><\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<\/tr>\n<tr>\n<td><b>Merge-on-Read запросы<\/b><\/td>\n<td>✅ Snapshot Query<\/td>\n<td>❌ Сложная поддержка<\/td>\n<td>✅ Все запросы мержат векторы удалений<\/td>\n<\/tr>\n<tr>\n<td><b>Инкрементальные запросы<\/b><\/td>\n<td>✅ + CDC запросы<\/td>\n<td>✅ CDF (эксперимент.)<\/td>\n<td>❌ Только аппенды<\/td>\n<\/tr>\n<tr>\n<td><b>CDC запросы<\/b><\/td>\n<td>✅ + before\/after images<\/td>\n<td>❌<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Вторичные индексы<\/b><\/td>\n<td>✅<\/td>\n<td>❌<\/td>\n<td>❌<\/td>\n<\/tr>\n<tr>\n<td><b>Предикаты для пропуска данных<\/b><\/td>\n<td>✅ Индексы выражений<\/td>\n<td>✅ Логические предикаты<\/td>\n<td>✅ Трансформации таблиц<\/td>\n<\/tr>\n<\/table>\n<h3>Сервисы таблиц<\/h3>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Функция<\/td>\n<td>Apache Hudi<\/td>\n<td>Delta Lake<\/td>\n<td>Apache Iceberg<\/td>\n<\/tr>\n<tr>\n<td><b>Авторазмер файлов<\/b><\/td>\n<td>✅<\/td>\n<td>✅<\/td>\n<td>❌ Ручное управление<\/td>\n<\/tr>\n<tr>\n<td><b>Компактизация<\/b><\/td>\n<td>✅ Управляемая<\/td>\n<td>❌ 2-этапное обслуживание<\/td>\n<td>❌ Ручное обслуживание<\/td>\n<\/tr>\n<tr>\n<td><b>Очистка<\/b><\/td>\n<td>✅ Управляемая<\/td>\n<td>❌ VACUUM вручную<\/td>\n<td>❌ Ручное удаление снапшотов<\/td>\n<\/tr>\n<tr>\n<td><b>Кластеризация<\/b><\/td>\n<td>✅ Авто + Z-order\/Hilbert<\/td>\n<td>❌ Z-order в OSS, авто – проприетар.<\/td>\n<td>❌ Z-order вручную<\/td>\n<\/tr>\n<\/table>\n<h3>Поддержка экосистемы<\/h3>\n<p>Все три формата имеют широкую поддержку в экосистеме данных:<\/p>\n<ul>\n<li><b>Apache Spark, Flink, Trino, DBT<\/b> – полная поддержка чтения\/записи во всех форматах<\/li>\n<li><b>Kafka Connect<\/b> – Hudi и Iceberg имеют нативную поддержку, Delta – только проприетарную<\/li>\n<li><b>Облачные платформы<\/b> (AWS, GCP, Azure) – все три формата поддерживаются с некоторыми ограничениями<\/li>\n<li><b>Snowflake<\/b> – нативная поддержка Iceberg, Hudi через XTable<\/li>\n<\/ul>\n<h3>Производительность: TPC-DS бенчмарки<\/h3>\n<p>Согласно независимым тестам:<\/p>\n<ul>\n<li><b>Hudi<\/b> и <b>Delta<\/b> показывают сопоставимую производительность<\/li>\n<li><b>Iceberg<\/b> consistently отстаёт по скорости выполнения запросов<\/li>\n<\/ul>\n<blockquote>\n<p><b>Важно:<\/b> При сравнении производительности учитывайте, что Hudi по умолчанию оптимизирован для mutable-нагрузок (upsert), в то время как Delta и Iceberg – для append-only. Для честного сравнения используйте `bulk-insert` режим в Hudi.<\/p>\n<\/blockquote>\n<h3>Ключевые дифференцирующие возможности<\/h3>\n<h3>Инкрементальные пайплайн<\/h3>\n<p><b>Hudi<\/b> предлагает наиболее зрелую поддержку инкрементальной обработки с трекингом всех изменений (вставки, обновления, удаления) и предоставлением их в виде change streams. Это позволяет строить эффективные ETL-пайплайны без перевычисления полных наборов данных.<\/p>\n<h3>Управление конкуренцией<\/h3>\n<p>В то время как все три системы поддерживают оптимистический контроль конкуренции (OCC), только <b>Hudi<\/b> предлагает:<\/p>\n<ul>\n<li>Неблокирующий контроль конкуренции (NBCC)<\/li>\n<li>Файл-уровневую гранулярность блокировок<\/li>\n<li>Возможность работы с асинхронными сервисами таблиц без остановки записи<\/li>\n<\/ul>\n<h3>Merge-on-Read<\/h3>\n<p>Только <b>Hudi<\/b> предоставляет полнофункциональный Merge-on-Read, который позволяет:<\/p>\n<ul>\n<li>Балансировать между производительностью записи и чтения<\/li>\n<li>Использовать row-ориентированные форматы для стриминга и column-ориентированные для аналитики<\/li>\n<li>Выполнять компактизацию асинхронно<\/li>\n<\/ul>\n<h3>Кластеризация vs Эволюция партиций<\/h3>\n<ul>\n<li><b>Iceberg<\/b>: Partition Evolution – изменение схемы партиционирования для новых данных<\/li>\n<li><b>Hudi<\/b>: Гибридный подход – coarse-grained партиционирование + fine-grained кластеризация с возможностью эволюции без перезаписи данных<\/li>\n<\/ul>\n<h3>Многомодальное индексирование<\/h3>\n<p>Только <b>Hudi<\/b> предлагает асинхронную подсистему индексирования, поддерживающую:<\/p>\n<ul>\n<li>Bloom, hash, bitmap, R-tree индексы<\/li>\n<li>10-100x ускорение point lookup запросов<\/li>\n<li>10-30x общее ускорение запросов в реальных нагрузках<\/li>\n<\/ul>\n<h3>Реальные кейсы использования<\/h3>\n<h3>Peloton<\/h3>\n<ul>\n<li>Увеличение частоты ингестии с 1 раза в день до каждых 10 минут<\/li>\n<li>Снижение времени выполнения снапшот-заданий с 1 часа до 15 минут<\/li>\n<li>Экономия затрат через оптимизацию использования EMR-кластеров<\/li>\n<\/ul>\n<h3>ByteDance\/TikTok<\/h3>\n<ul>\n<li>Обработка таблиц объемом 400+ PB<\/li>\n<li>Ежедневный прирост данных на уровне PB<\/li>\n<li>Пропускная способность >100 GB\/s на таблицу<\/li>\n<li>Выбор Hudi из-за открытости экосистемы и поддержки глобальных индексов<\/li>\n<\/ul>\n<h3>Walmart<\/h3>\n<ul>\n<li>Использование Merge-on-Read для снижения задержек<\/li>\n<li>Нативная поддержка удалений для GDPR\/CCPA compliance<\/li>\n<li>Row versioning для обработки out-of-order данных<\/li>\n<\/ul>\n<h3>Инновации сообщества<\/h3>\n<p>Многие ключевые функции data lakehouse были впервые реализованы в Hudi:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td>Инновация Hudi<\/td>\n<td>Год<\/td>\n<td>Аналог в других проектах<\/td>\n<\/tr>\n<tr>\n<td>Транзакционные обновления<\/td>\n<td>2017<\/td>\n<td>Delta OSS (2019)<\/td>\n<\/tr>\n<tr>\n<td>Merge-on-Read<\/td>\n<td>2017<\/td>\n<td>Iceberg (2021)<\/td>\n<\/tr>\n<tr>\n<td>Инкрементальные запросы<\/td>\n<td>2017<\/td>\n<td>Delta Change Feed (2022)<\/td>\n<\/tr>\n<tr>\n<td>Z-order\/Hilbert кривые<\/td>\n<td>2021<\/td>\n<td>Delta OSS (2022)<\/td>\n<\/tr>\n<tr>\n<td>Многомодальное индексирование<\/td>\n<td>2022<\/td>\n<td>❌ Нет аналогов<\/td>\n<\/tr>\n<tr>\n<td>Контроль конкуренции без блокировок<\/td>\n<td>2024<\/td>\n<td>❌ Нет аналогов<\/td>\n<\/tr>\n<\/table>\n<h3>Заключение<\/h3>\n<h3>Критерии выбора<\/h3>\n<p><b>Выбирайте Apache Hudi если:<\/b><\/p>\n<ul>\n<li>Ваши workload’ы содержат значительное количество обновлений и удалений<\/li>\n<li>Требуется низкая задержка от конца в конец<\/li>\n<li>Нужны продвинутые возможности управления конкуренцией<\/li>\n<li>Важна производительность point lookup запросов<\/li>\n<li>Требуется гибкое управление layout данных через кластеризацию<\/li>\n<\/ul>\n<p><b>Рассмотрите Delta Lake если:<\/b><\/p>\n<ul>\n<li>Вы используете экосистему Databricks<\/li>\n<li>Workload’ы преимущественно append-only<\/li>\n<li>Достаточно базовых возможностей управления конкуренцией<\/li>\n<\/ul>\n<p><b>Apache Iceberg может подойти если:<\/b><\/p>\n<ul>\n<li>Основная задача – работа с очень большими объемами данных в cloud storage<\/li>\n<li>Требуется скрытое партиционирование с эволюцией<\/li>\n<li>Workload’ы в основном аналитические с минимальными обновлениями<\/li>\n<\/ul>\n<h3>Итоговые рекомендации<\/h3>\n<ol start=\"1\">\n<li><b>Для зрелых production-нагрузок<\/b> с frequent updates, high concurrency и low latency требованиями <b>Apache Hudi<\/b> предлагает наиболее полный набор возможностей.<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Не ограничивайтесь сравнением “галочек”<\/b> – оценивайте производительность на своих данных и workload’ах.<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Рассмотрите Apache XTable<\/b> если невозможно определиться с одним форматом или требуется интероперабельность между системами.<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Учитывайте roadmap проекта<\/b> – Hudi продолжает лидировать в инновациях, что может быть важно для долгосрочных инвестиций.<\/li>\n<\/ol>\n<p>Технологии data lakehouse продолжают быстро развиваться, и выбор должен основываться на конкретных требованиях ваших use cases, а не только на текущем состоянии функциональности.<\/p>\n",
            "date_published": "2025-11-01T00:53:55+03:00",
            "date_modified": "2025-11-01T00:53:37+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer",
                "Iceberg"
            ],
            "_date_published_rfc2822": "Sat, 01 Nov 2025 00:53:55 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "291",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "286",
            "url": "https:\/\/gavrilov.info\/all\/bitva-novyh-arhitektur-sravnivaem-arc-gigapi-i-ducklake\/",
            "title": "Битва Новых Архитектур: Сравниваем Arc, GigAPI и DuckLake",
            "content_html": "<p>В мире данных происходит тихая революция. На смену тяжеловесным и дорогим OLAP-системам приходят легковесные, но мощные решения, построенные на идеологии Lakehouse. Они обещают гибкость озер данных и надежность хранилищ без лишней сложности и затрат.<\/p>\n<p>Можно еще почитать тут: <a href=\"https:\/\/habr.com\/ru\/articles\/955536\/\">https:\/\/habr.com\/ru\/articles\/955536\/<\/a><\/p>\n<p>В этой статье мы сравним два таких проекта для работы с временными рядами — <b>Arc<\/b> и <b>GigAPI<\/b>. А также разберемся, какое место в этой экосистеме занимает <b>DuckLake<\/b> — технология, которую пока еще могут путать с Arc.<\/p>\n<h4>🆚 Arc vs. GigAPI: Сравнительная таблица<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-220.png\" width=\"1024\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-221.png\" width=\"769\" height=\"232\" alt=\"\" \/>\n<\/div>\n<p>Это прямые конкуренты, решающие задачу хранения и анализа временных рядов, но с разной философией.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\"><b>Параметр<\/b><\/td>\n<td style=\"text-align: center\"><b>Arc<\/b><\/td>\n<td style=\"text-align: center\"><b>GigAPI<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Основной подход<\/b><\/td>\n<td style=\"text-align: center\">Автономная Time-Series база данных «в одном файле» на базе DuckDB.<\/td>\n<td style=\"text-align: center\">Унифицированный слой для запросов и управления жизненным циклом данных (Lakehouse).<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Стадия развития<\/b><\/td>\n<td style=\"text-align: center\">Альфа, <b>не для продакшена<\/b>.<\/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\">Монолитный бинарный файл, простой запуск.<\/td>\n<td style=\"text-align: center\">Набор микросервисов (`aio`, `readonly`, `writeonly`, `compaction`).<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right\"><b>Производительность (ingest)<\/b><\/td>\n<td style=\"text-align: center\">Заявлено до <b>~1.89 млн записей\/сек<\/b> (нативным протоколом).<\/td>\n<td style=\"text-align: center\">Субсекундные аналитические запросы. Производительность ingest зависит от бэкенда.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Протоколы ввода данных<\/b><\/td>\n<td style=\"text-align: center\">MessagePack (рекомендуемый), InfluxDB Line Protocol <a href=\"https:\/\/github.com\/Basekick-Labs\/arc\">arc<\/a>.<\/td>\n<td style=\"text-align: center\">InfluxDB Line Protocol, Native JSON. Планируется FlightSQL <a href=\"https:\/\/github.com\/gigapi\/gigapi\">gigapi<\/a>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Управление данными<\/b><\/td>\n<td style=\"text-align: center\">ACID-транзакции, Time Travel, Schema Evolution (унаследовано от Lakehouse-архитектуры).<\/td>\n<td style=\"text-align: center\"><b>Автоматическая компакция<\/b>, <b>перемещение данных (tiering)<\/b> между FS и S3, <b>удаление по TTL<\/b>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Лицензия<\/b><\/td>\n<td style=\"text-align: center\"><b>AGPL-3.0<\/b> (важное ограничение для коммерческого использования).<\/td>\n<td style=\"text-align: center\"><b>MIT<\/b> (максимально разрешительная).<\/td>\n<\/tr>\n<\/table>\n<h4>Ключевые отличия в подходах: Arc и GigAPI<\/h4>\n<h5>Arc: Максимальная простота и скорость для старта<\/h5>\n<p><b>Arc<\/b> <a href=\"https:\/\/github.com\/Basekick-Labs\/arc\">arc<\/a> — это полноценная база данных временных рядов, которую можно скачать и запустить одной командой.<\/p>\n<ul>\n<li><b>Идеология:<\/b> “Батарейки в комплекте”. Arc предоставляет готовое решение с ACID-транзакциями, time travel и эволюцией схемы “из коробки”. Он спроектирован для максимальной простоты развертывания и сверхбыстрого приема данных.<\/li>\n<li><b>Сценарий использования:<\/b> Идеален для R&D, прототипирования и внутренних проектов, где нужна высокая производительность без сложной настройки.<\/li>\n<li><b>Ключевой компромисс:<\/b> Лицензия AGPL-3.0 требует, чтобы любое сетевое приложение, использующее Arc, также открывало свой исходный код. Это делает его неприменимым для многих коммерческих продуктов.<\/li>\n<\/ul>\n<h5>GigAPI: Операционная мощь для продакшена<\/h5>\n<p><b>GigAPI<\/b> <a href=\"https:\/\/github.com\/gigapi\/gigapi\">gigapi<\/a> — это не база данных, а скорее <b>интеллектуальный операционный слой<\/b> или шлюз, который работает поверх ваших данных.<\/p>\n<ul>\n<li><b>Идеология:<\/b> “Оркестратор и оптимизатор”. GigAPI фокусируется на промышленной эксплуатации и автоматизации рутинных задач. Его микросервисы (`merge`, `move`, `drop`) следят за здоровьем хранилища: уплотняют мелкие файлы, перемещают старые данные в дешевое S3-хранилище и удаляют их по истечении срока жизни (TTL).<\/li>\n<li><b>Сценарий использования:<\/b> Построение зрелого, экономически эффективного и надежного пайплайна для временных рядов в production-среде. Разрешительная лицензия MIT делает его отличным выбором для бизнеса.<\/li>\n<li><b>Ключевое преимущество:<\/b> Архитектурная гибкость и фокус на снижении эксплуатационных расходов (OpEx).<\/li>\n<\/ul>\n<h4>А где же DuckLake?<\/h4>\n<p><b>DuckLake<\/b> — это не база данных, а <b>открытый табличный формат<\/b> и <b>расширение для DuckDB<\/b> <a href=\"https:\/\/github.com\/duckdb\/ducklake\">ducklake<\/a>. Его цель — упростить создание Lakehouse, используя SQL в качестве слоя метаданных <a href=\"https:\/\/duckdb.org\/2025\/05\/27\/ducklake.html\">ducklake blog<\/a>.<\/p>\n<p>Представьте, что у вас есть набор Parquet-файлов в S3. Чтобы работать с ними как с единой таблицей и иметь транзакции, традиционно нужен сложный компонент вроде Hive Metastore или Nessie. DuckLake предлагает более простой путь:<\/p>\n<blockquote>\n<p>Используйте обычную SQL-базу (например, DuckDB, SQLite или даже Postgres) для хранения всей метаинформации о файлах, версиях и схеме.<\/p>\n<\/blockquote>\n<p>Таким образом, DuckLake — это <b>фундаментальный строительный блок<\/b>, а не готовое приложение. Он конкурирует с Apache Iceberg и Delta Lake, предлагая более простую альтернативу. Недавние обновления даже добавили <b>совместимость с Iceberg<\/b>, что делает его еще более мощным инструментом <a href=\"https:\/\/ducklake.select\/2025\/09\/17\/ducklake-03\/\">ducklake.select<\/a>.<\/p>\n<h4>Сравнение с рынком: Альтернативы и выбор<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\"><b>Система<\/b><\/td>\n<td style=\"text-align: center\"><b>Сильные стороны<\/b><\/td>\n<td style=\"text-align: center\"><b>Слабые стороны \/ Риски<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>InfluxDB 3.0<\/b><\/td>\n<td style=\"text-align: center\">Зрелая экосистема для временных рядов, Lakehouse архитектура “под капотом”.<\/td>\n<td style=\"text-align: center\">Стоимость для enterprise, привязка к своей экосистеме.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>QuestDB<\/b><\/td>\n<td style=\"text-align: center\">Высокая скорость вставок и SQL-запросов, простой опыт TSDB.<\/td>\n<td style=\"text-align: center\">Менее универсален для “озер” на S3, чем конкуренты.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>TimescaleDB<\/b><\/td>\n<td style=\"text-align: center\">Полная совместимость с экосистемой PostgreSQL.<\/td>\n<td style=\"text-align: center\">Привязанность к PostgreSQL и его модели масштабирования.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>ClickHouse<\/b><\/td>\n<td style=\"text-align: center\">Универсальный OLAP-движок, мощные возможности для временных рядов, горизонтальное масштабирование.<\/td>\n<td style=\"text-align: center\">Высокие эксплуатационные расходы, сложность настройки кластера.<\/td>\n<\/tr>\n<\/table>\n<h4>Когда что выбирать?<\/h4>\n<ul>\n<li><b>Выберите Arc<\/b>, если вам нужен <b>максимально быстрый старт<\/b> для прототипа или внутреннего проекта, вы не боитесь альфа-версии и вас полностью устраивает <b>лицензия AGPL-3.0<\/b>.<\/li>\n<\/ul>\n<ul>\n<li><b>Выберите GigAPI<\/b>, если вы строите <b>продакшн-систему<\/b>, вам важна <b>автоматизация рутинных задач<\/b> (compaction, tiering, TTL) и нужна <b>разрешительная лицензия MIT<\/b> для коммерческого использования.<\/li>\n<\/ul>\n<ul>\n<li><b>Используйте DuckLake<\/b>, если вы уже работаете с DuckDB и хотите построить <b>свой собственный, простой Lakehouse<\/b> на базе Parquet-файлов, избегая сложности стека Hadoop\/Spark.<\/li>\n<\/ul>\n<ul>\n<li><b>Обратитесь к ClickHouse\/Druid<\/b>, когда нужны <b>жесткие SLA, горизонтальное масштабирование<\/b> и высокий параллелизм для тысяч одновременных пользователей.<\/li>\n<\/ul>\n<ul>\n<li><b>Рассмотрите QuestDB\/Timescale<\/b>, если приоритетом является <b>предельно простой опыт работы с TSDB<\/b> или глубокая интеграция с экосистемой Postgres.<\/li>\n<\/ul>\n<h4>Заключение<\/h4>\n<p><b>Arc<\/b>, <b>GigAPI<\/b> и <b>DuckLake<\/b> — яркие представители тренда на прагматичные и экономичные решения для данных.<\/p>\n<ul>\n<li><b>Arc<\/b> — спринтер для быстрого старта.<\/li>\n<li><b>GigAPI<\/b> — марафонец для надежной работы в продакшене.<\/li>\n<li><b>DuckLake<\/b> — набор инструментов для архитектора, позволяющий построить легковесный и современный дом для данных.<\/li>\n<\/ul>\n<p>Их появление говорит о том, что рынку нужны не только монструозные системы, но и решения с оптимальным соотношением “простота\/стоимость\/функциональность”.<\/p>\n<p>Вот так выглядит:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-11-v-23.58.08.png\" width=\"2094\" height=\"1162\" alt=\"\" \/>\n<\/div>\n<pre class=\"e2-text-code\"><code class=\"\">services:\n  gigapi:\n    image: ghcr.io\/gigapi\/gigapi:latest\n    container_name: gigapi\n    hostname: gigapi\n    restart: unless-stopped\n    volumes:\n      - .\/data:\/data\n    ports:\n      - &quot;7971:7971&quot;\n      - &quot;8082:8082&quot;\n    environment:\n      - PORT=7971\n      - GIGAPI_ENABLED=true\n      - GIGAPI_MERGE_TIMEOUT_S=10\n      - GIGAPI_ROOT=\/data\n      - GIGAPI_LAYERS_0_NAME=default\n      - GIGAPI_LAYERS_0_TYPE=fs\n      - GIGAPI_LAYERS_0_URL=file:\/\/\/data\n      - GIGAPI_LAYERS_0_GLOBAL=false\n      - GIGAPI_LAYERS_0_TTL=12h\n      - GIGAPI_LAYERS_1_NAME=s3\n      - GIGAPI_LAYERS_1_TYPE=s3\n      - GIGAPI_LAYERS_1_URL=s3:\/\/gateway.XXXXX\/test\/gigapi\n      - GIGAPI_LAYERS_1_AUTH_KEY=XXXXX\n      - GIGAPI_LAYERS_1_AUTH_SECRET=XXXXX\n      - GIGAPI_LAYERS_1_GLOBAL=true\n      - GIGAPI_LAYERS_1_TTL=0<\/code><\/pre><p>А данные пишем так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">cat &lt;&lt;EOF | curl -X POST &quot;http:\/\/localhost:7971\/write?db=mydb&quot; --data-binary @\/dev\/stdin\nweather,location=us-midwest,season=summer temperature=82\nweather,location=us-east,season=summer temperature=123\nweather,location=us-west,season=summer temperature=111\nEOF<\/code><\/pre><p>Первый раз нужно отправить сообщение, что бы создалась база.<\/p>\n<p>файлики пишет, но че то пока не на s3, видимо надо дождаться как они переедут с кеша на s3<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-12-v-00.01.54.png\" width=\"924\" height=\"444\" alt=\"\" \/>\n<\/div>\n<p>Выше пример не сработал, точнее он работал, но не копировал данные на s3<\/p>\n<p>вот это рабочий вариант<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># docker-compose.yml\nversion: '3.8'\n\nservices:\n  gigapi:\n    build: . \n    container_name: gigapi\n    restart: unless-stopped\n    volumes:\n      - .\/gigapi_data:\/data\n    ports:\n      - &quot;7971:7971&quot;\n      - &quot;8082:8082&quot;\n    environment:\n      # --- Общие настройки GigAPI ---\n      - GIGAPI_ROOT=\/data \n      - HTTP_PORT=7971\n      - LOGLEVEL=info\n      - GIGAPI_UI=true\n\n      # --- Конфигурация Слоя 0: Локальный кэш на диске ---\n      - GIGAPI_LAYERS_0_NAME=local_cache\n      - GIGAPI_LAYERS_0_TYPE=fs\n      - GIGAPI_LAYERS_0_URL=file:\/\/\/data\/cache\n      - GIGAPI_LAYERS_0_GLOBAL=false\n      - GIGAPI_LAYERS_0_TTL=10m\n\n      # --- Конфигурация Слоя 1: Хранилище Storj S3 ---\n      - GIGAPI_LAYERS_1_NAME=storj_s3\n      - GIGAPI_LAYERS_1_TYPE=s3\n      - GIGAPI_LAYERS_1_URL=s3:\/\/gateway.storjshare.io\/test\/gigapi\/data?url-style=path\n      - GIGAPI_LAYERS_1_AUTH_KEY=XXXXXX\n      - GIGAPI_LAYERS_1_AUTH_SECRET=XXXXX\n      - GIGAPI_LAYERS_1_GLOBAL=true\n      - GIGAPI_LAYERS_1_TTL=0<\/code><\/pre><p>И пришлось серты обновить<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Dockerfile\n\n# Берем за основу официальный образ gigapi\nFROM ghcr.io\/gigapi\/gigapi:latest\n\n# Переключаемся на пользователя root для установки пакетов\nUSER root\n\n# Обновляем список пакетов и устанавливаем корневые сертификаты.\n# Эта команда сначала пытается использовать 'apt-get' (для Debian\/Ubuntu).\n# Если эта команда завершается с ошибкой (оператор ||), то\n# выполняется вторая команда с 'apk' (для Alpine).\n# Это делает Dockerfile более универсальным.\nRUN if command -v apt-get &amp;&gt; \/dev\/null; then \\\n        apt-get update &amp;&amp; apt-get install -y --no-install-recommends ca-certificates &amp;&amp; apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*; \\\n    elif command -v apk &amp;&gt; \/dev\/null; then \\\n        apk add --no-cache ca-certificates; \\\n    else \\\n        echo &quot;Error: Neither apt-get nor apk found. Cannot install ca-certificates.&quot; &gt;&amp;2; \\\n        exit 1; \\\n    fi\n\n# Возвращаемся к стандартному пользователю (если он есть)\n# USER gigapi<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.34.22.png\" width=\"1492\" height=\"176\" alt=\"\" \/>\n<\/div>\n<p>Там кстати еще чатгпт апи можно вставить<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.37.35.png\" width=\"1588\" height=\"1216\" alt=\"\" \/>\n<\/div>\n<p>И дашборды есть еще<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.39.54.png\" width=\"1710\" height=\"642\" alt=\"\" \/>\n<\/div>\n<p>Еще про s3 подобные архитектуры:<br \/>\n<a href=\"https:\/\/gavrilov.info\/all\/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la\">https:\/\/gavrilov.info\/all\/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la<\/a><\/p>\n",
            "date_published": "2025-10-12T00:02:44+03:00",
            "date_modified": "2025-10-14T23:19:00+03:00",
            "tags": [
                "big data",
                "Data",
                "Database"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-220.png",
            "_date_published_rfc2822": "Sun, 12 Oct 2025 00:02:44 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "286",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-220.png",
                    "https:\/\/gavrilov.info\/pictures\/image-221.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-11-v-23.58.08.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-12-v-00.01.54.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.34.22.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.37.35.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.39.54.png"
                ]
            }
        },
        {
            "id": "280",
            "url": "https:\/\/gavrilov.info\/all\/svodnaya-statya-osnovy-proektirovaniya-sovremennogo-hranilischa\/",
            "title": "Сводная статья: Основы проектирования современного хранилища данных",
            "content_html": "<p>Эта статья объединяет два материала из блога Apache SeaTunnel, посвященных фундаментальным принципам построения современных аналитических платформ. Мы рассмотрим перевод оригинальных текстов и затем погрузимся в детальный разбор упомянутой методологии.<\/p>\n<p>Источник: Apache SeaTunnel’s Substack<br \/>\nДаты: 5 сентября 2025 г. и 14 сентября 2025 г.<\/p>\n<hr \/>\n<h5><b>Часть 1: Сводный перевод статей<\/b><\/h5>\n<h6><b>(I) Принципы архитектуры модели данных: Четыре уровня и семь этапов, «краеугольный камень» моделирования Data Lake и хранилищ данных<\/b><\/h6>\n<blockquote>\n<p>Руководство по проектированию и практическому применению Data Lake и хранилищ данных (2025) состоит из четырех последовательных частей. Следуя основной линии «архитектура модели – общие спецификации – спецификации наслоения – спецификации именования», оно позволяет системно построить современное озеро данных (data lake) и хранилище, которое может развиваться, управляться и использоваться совместно.<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/substack.com\/home\/post\/p-172756839\">https:\/\/substack.com\/home\/post\/p-172756839<\/a><\/p>\n<h6><b>(II) Полное руководство по основным стандартам проектирования хранилищ данных: от уровней и типов до жизненного цикла<\/b><\/h6>\n<blockquote>\n<p>Руководство по проектированию и практическому применению Data Lakehouse: стандарты моделирования и именования для Data Lakehouse (2025)» состоит из четырех прогрессивных руководств, структурированных по основной линии: Архитектура модели — Общие стандарты — Стандарты наслоения — Стандарты именования. Вместе они позволяют системно построить развиваемое, управляемое и совместно используемое современное data lakehouse.<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/substack.com\/home\/post\/p-173419940\">https:\/\/substack.com\/home\/post\/p-173419940<\/a><\/p>\n<hr \/>\n<h5><b>Часть 2: Разбор методологии — от уровней до жизненного цикла<\/b><\/h5>\n<p>Статьи описывают структурированный подход к созданию современных аналитических систем. Эта методология основана на нескольких ключевых концепциях, которые мы разберем подробно.<\/p>\n<p>Основная цель — создать «развиваемое, управляемое и совместно используемое» хранилище. Это означает, что система должна быть:<\/p>\n<ul>\n<li><b>Развиваемой:<\/b> Легко адаптируемой к новым источникам данных и бизнес-требованиям без необходимости полной перестройки.<\/li>\n<li><b>Управляемой:<\/b> Иметь четкие правила качества данных, безопасности и контроля доступа.<\/li>\n<li><b>Совместно используемой:<\/b> Данные должны быть понятны и доступны для разных команд и отделов компании.<\/li>\n<\/ul>\n<p>Основой для этого служит подход, который статьи называют <b>«основной линией»<\/b>:<\/p>\n<ol start=\"1\">\n<li><b>Архитектура модели:<\/b> Общий план строения хранилища.<\/li>\n<li><b>Общие спецификации:<\/b> Единые правила для всей системы (например, форматы дат, стандарты кодирования).<\/li>\n<li><b>Спецификации наслоения:<\/b> Правила и состав данных для каждого архитектурного уровня.<\/li>\n<li><b>Спецификации именования:<\/b> Единые правила наименования таблиц, полей и других объектов для их легкой идентификации (например, `fct_` для таблиц фактов, `dim_` для измерений, `mart_` для витрин).<\/li>\n<\/ol>\n<h6>Четыре архитектурных уровня<\/h6>\n<p>Это — костяк всей системы, по которому данные движутся и преобразуются от “сырых” до готовых к анализу.<\/p>\n<p><b>1. `ODS` (Operational Data Store — Оперативное хранилище данных)<\/b><\/p>\n<ul>\n<li><b>Назначение:<\/b> Первый слой для приема данных из различных систем-источников (базы данных сайта, CRM, ERP, мобильные приложения).<\/li>\n<li><b>Состояние данных:<\/b> «Сырые» или минимально обработанные данные. Их структура максимально приближена к оригиналу. Этот слой служит буфером и архивом.<\/li>\n<li><b>Пример:<\/b> Каждый час система автоматически копирует новые записи о заказах из базы данных интернет-магазина и данные о клиентах из CRM в отдельные таблицы в слое `ODS`. Данные хранятся “как есть”.<\/li>\n<\/ul>\n<p><b>2. `DW` (Data Warehouse — Хранилище данных)<\/b><br \/>\nЭто центральный и самый сложный слой, где происходит основная магия: очистка, интеграция и моделирование данных. Он делится на три подслоя:<\/p>\n<ul>\n<li><b>`DWD` (Data Warehouse Detail — Детальный слой)<\/b>\n<ul>\n  <li><b>Назначение:<\/b> Создание «единого источника правды». Данные из `ODS` очищаются, унифицируются (например, все статусы “Доставлен”, “delivered”, “Complete” приводятся к единому формату `delivered`) и связываются между собой.<\/li>\n  <li><b>Состояние данных:<\/b> Очищенные, детализированные, исторически полные данные. Здесь хранятся все транзакции и события в их самой гранулярной форме.<\/li>\n  <li><b>Пример:<\/b> На основе сырых данных о заказах из `ODS` создается таблица `dwd_orders`, где у каждого заказа есть уникальный идентификатор, ссылка на клиента, очищенный статус и стандартизированная дата.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li><b>`DWM` (Data Warehouse Middle — Промежуточный слой \/ Слой моделей)<\/b>\n<ul>\n  <li><b>Назначение:<\/b> Агрегация и трансформация данных для бизнес-аналитики. Здесь детальные данные из `DWD` преобразуются в модели «звезда» или «снежинка», состоящие из фактов (события, транзакции) и измерений (справочники).<\/li>\n  <li><b>Состояние данных:<\/b> Структурированные, готовые для анализа данные.<\/li>\n  <li><b>Пример:<\/b> На основе `dwd_orders` создается таблица фактов `fct_sales` (содержащая количество, сумму, скидку) и связанные с ней таблицы-измерения: `dim_customers` (клиенты), `dim_products` (товары), `dim_calendar` (календарь).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li><b>`DWS` (Data Warehouse Service\/Summary — Слой витрин данных)<\/b>\n<ul>\n  <li><b>Назначение:<\/b> Предоставление данных конечным пользователям. Витрина — это набор данных, подготовленный для конкретного отдела или задачи.<\/li>\n  <li><b>Состояние данных:<\/b> Предварительно агрегированные, узкоспециализированные данные.<\/li>\n  <li><b>Пример:<\/b> Для отдела маркетинга создается витрина `mart_marketing_performance`, где продажи агрегированы по дням, рекламным кампаниям и регионам. Это позволяет маркетологам быстро оценивать эффективность своих действий, не обращаясь к сложным моделям слоя `DWM`.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><b>3. `APP` (Application — Слой приложений)<\/b><\/p>\n<ul>\n<li><b>Назначение:<\/b> Слой визуализации и потребления данных. С ним работают конечные бизнес-пользователи.<\/li>\n<li><b>Пример:<\/b> BI-системы (Power BI, Tableau, Looker), которые подключаются к витринам данных в `DWS` и строят на их основе интерактивные дашборды, графики и отчеты.<\/li>\n<\/ul>\n<h6>Семь этапов жизненного цикла данных<\/h6>\n<p>Хотя в статьях этапы не расшифровываются, они логически вытекают из описанной архитектуры и представляют собой полный путь данных от источника до пользователя.<\/p>\n<ol start=\"1\">\n<li><b>Сбор (Source):<\/b> Определение и доступ к источникам данных (БД, API, файлы).<\/li>\n<li><b>Загрузка (Ingestion):<\/b> Перемещение данных из источников в слой `ODS`.<\/li>\n<li><b>Хранение (Storage):<\/b> Размещение сырых данных в операционном хранилище (`ODS`).<\/li>\n<li><b>Очистка и Интеграция (Cleansing & Integration):<\/b> Преобразование данных и создание детального слоя (`DWD`).<\/li>\n<li><b>Моделирование (Modeling):<\/b> Построение аналитических моделей (таблиц фактов и измерений) в слое `DWM`.<\/li>\n<li><b>Агрегация (Aggregation\/Serving):<\/b> Создание витрин данных для конкретных нужд в слое `DWS`.<\/li>\n<li><b>Визуализация и Анализ (Visualization & Analysis):<\/b> Потребление данных через BI-инструменты в слое `APP`.<\/li>\n<\/ol>\n<hr \/>\n<h5><b>Итог: Создание современного хранилища данных<\/b><\/h5>\n<p>Представленная методология — это не просто техническая инструкция, а фундаментальная философия управления данными. В мире, где данные часто хаотичны и разрозненны, такой структурированный подход позволяет навести порядок.<\/p>\n<p>Разделение на слои решает несколько ключевых проблем:<\/p>\n<ul>\n<li><b>Изоляция изменений:<\/b> Изменение в системе-источнике повлияет только на слой `ODS`, а не на всё хранилище.<\/li>\n<li><b>Надежность:<\/b> Данные проходят последовательную проверку и обогащение, что повышает доверие к ним.<\/li>\n<li><b>Производительность:<\/b> Пользователи работают с быстрыми, предварительно агрегированными витринами данных (`DWS`), а не с огромными детализированными таблицами.<\/li>\n<\/ul>\n<p>Таким образом, следование принципам <b>четырех уровней и семи этапов<\/b> позволяет построить не просто базу данных, а надежную, масштабируемую и понятную аналитическую платформу, которая становится настоящим «краеугольным камнем» для принятия решений на основе данных в любой современной компании.<\/p>\n",
            "date_published": "2025-09-16T23:51:51+03:00",
            "date_modified": "2025-09-16T23:51:35+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Governance"
            ],
            "_date_published_rfc2822": "Tue, 16 Sep 2025 23:51:51 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "280",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "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": "270",
            "url": "https:\/\/gavrilov.info\/all\/apache-seatunnel-dvizhenie-k-multimodalnoy-integracii-dannyh\/",
            "title": "Apache SeaTunnel – Движение к мультимодальной интеграции данных",
            "content_html": "<h4>Новое позиционирование Apache SeaTunnel. Движение к унифицированному инструменту для мультимодальной интеграции данных<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-209.png\" width=\"1456\" height=\"840\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Оригинал тут: <a href=\"https:\/\/apacheseatunnel.substack.com\/p\/apache-seatunnel-new-positioning\">https:\/\/apacheseatunnel.substack.com\/p\/apache-seatunnel-new-positioning<\/a><\/div>\n<\/div>\n<h4>Введение<\/h4>\n<p>В постоянно меняющемся мире больших данных эффективная и надежная интеграция данных является ключевым фактором для успеха любого предприятия. Apache SeaTunnel (ранее известный как Waterdrop) зарекомендовал себя как мощный инструмент для синхронизации данных. Однако с развитием технологий и появлением новых вызовов, таких как интеграция разнородных типов данных (структурированных, полуструктурированных и неструктурированных), проект пересматривает свое позиционирование. Цель — превратиться из простого инструмента синхронизации в комплексную, унифицированную платформу для мультимодальной интеграции данных.<\/p>\n<h4>Проблемы предыдущей архитектуры<\/h4>\n<p>Изначально Apache SeaTunnel был разработан как плагин, работающий поверх вычислительных движков, таких как Apache Spark и Apache Flink. Такой подход имел свои преимущества, позволяя использовать мощность этих движков, но также порождал ряд проблем:<\/p>\n<ol start=\"1\">\n<li><b>Зависимость от сторонних движков:<\/b> Для выполнения даже самых простых задач по пересылке данных требовалось развертывание и поддержка тяжеловесных кластеров Spark или Flink. Это увеличивало накладные расходы, усложняло настройку и повышало порог входа для новых пользователей.<\/li>\n<li><b>Сложность конфигурации:<\/b> Пользователям приходилось разбираться не только в конфигурации самого SeaTunnel, но и в настройках Spark\/Flink, что часто приводило к так называемому “конфигурационному аду”.<\/li>\n<li><b>Ограничения коннекторов:<\/b> Разработка коннекторов была тесно связана с API Spark и Flink, что затрудняло создание универсальных коннекторов, работающих в обеих средах без изменений.<\/li>\n<li><b>Низкая производительность для простых задач:<\/b> Использование мощных, но громоздких движков для элементарных задач ETL (Extract, Transform, Load) было избыточным и неэффективным с точки зрения ресурсов и времени запуска.<\/li>\n<\/ol>\n<h4>Новое видение: унифицированная платформа с собственным движком<\/h4>\n<p>Чтобы решить эти проблемы и соответствовать современным требованиям, сообщество Apache SeaTunnel представило новую архитектуру, в основе которой лежит собственный вычислительный движок — <b>SeaTunnel Engine<\/b>.<\/p>\n<p>Этот стратегический шаг позволил отделить SeaTunnel от обязательной зависимости от Spark и Flink. Теперь SeaTunnel может работать в самостоятельном режиме, что обеспечивает следующие ключевые преимущества:<\/p>\n<ul>\n<li><b>Легковесность и быстрота:<\/b> `SeaTunnel Engine` специально оптимизирован для задач интеграции данных. Он запускается быстрее и потребляет значительно меньше ресурсов, чем полноценные кластеры Spark или Flink, что делает его идеальным для широкого круга задач.<\/li>\n<li><b>Унификация пакетной и потоковой обработки:<\/b> Новая архитектура изначально спроектирована для бесшовной работы как с пакетными (batch), так и с потоковыми (streaming) данными. Пользователям больше не нужно поддерживать два разных стека для разных типов задач — SeaTunnel предоставляет единый интерфейс и модель выполнения.<\/li>\n<li><b>Упрощенная разработка коннекторов:<\/b> С введением унифицированного API коннекторов (`Connector API`), разработчикам стало проще создавать новые интеграции. Коннектор, написанный для `SeaTunnel Engine`, будет работать одинаково для всех сценариев, что ускоряет расширение экосистемы.<\/li>\n<\/ul>\n<h4>Мультимодальная интеграция данных<\/h4>\n<p>Ключевой аспект нового позиционирования — это поддержка <b>мультимодальных данных<\/b>. Это означает способность работать с данными различных форматов и из различных источников в рамках единого конвейера.<\/p>\n<ol start=\"1\">\n<li><b>Структурированные данные:<\/b> Традиционная область для SeaTunnel. Поддерживается множество реляционных баз данных (MySQL, PostgreSQL), аналитических СУБД (ClickHouse, Doris) и хранилищ данных.<\/li>\n<li><b>Полуструктурированные данные:<\/b> Эффективная работа с NoSQL базами данных (MongoDB, Elasticsearch) и потоками событий (Kafka, Pulsar).<\/li>\n<li><b>Неструктурированные данные:<\/b> Расширение поддержки для озер данных (Data Lakes) и файловых систем (HDFS, S3, OSS). Это включает интеграцию с форматами вроде Apache Hudi, Iceberg и Delta Lake.<\/li>\n<\/ol>\n<p>Особое внимание уделяется критически важным функциям, таким как <b>Захват изменяемых данных (CDC)<\/b> и <b>синхронизация всей базы данных целиком<\/b>. SeaTunnel теперь может считывать журналы транзакций (например, binlog в MySQL) для захвата изменений в реальном времени и применять их к целевой системе. Функция полной синхронизации позволяет в одной задаче перенести схему и все данные из одной базы в другую, что значительно упрощает миграцию.<\/p>\n<h4>Будущее развитие<\/h4>\n<p>Дорожная карта проекта включает в себя:<\/p>\n<ul>\n<li><b>Расширение экосистемы коннекторов:<\/b> Добавление поддержки еще большего числа источников и приемников, включая современные SaaS-платформы и векторные базы данных для задач ИИ.<\/li>\n<li><b>Улучшенная поддержка озер данных:<\/b> Углубление интеграции с форматами Hudi и Iceberg, поддержка эволюции схем и транзакционных операций.<\/li>\n<li><b>Пользовательский интерфейс:<\/b> Разработка визуального интерфейса для создания и мониторинга заданий, что сделает инструмент более доступным для широкого круга пользователей.<\/li>\n<li><b>Повышение производительности и стабильности:<\/b> Непрерывная оптимизация `SeaTunnel Engine` для еще более быстрой и надежной обработки данных.<\/li>\n<\/ul>\n<h4>Заключение<\/h4>\n<p>Apache SeaTunnel совершает важный переход от зависимого инструмента к самостоятельной, легковесной и унифицированной платформе для интеграции данных. Отказ от обязательной привязки к Spark\/Flink и внедрение собственного `SeaTunnel Engine` открывают новые возможности для пользователей, которым нужно простое, но мощное решение для пакетной и потоковой обработки разнородных данных. Новое позиционирование делает SeaTunnel сильным конкурентом в мире современных ETL\/ELT инструментов.<\/p>\n<p>---<\/p>\n<h5>Выводы<\/h5>\n<p>Проанализировав направление развитие Apache SeaTunnel, можно сделать несколько ключевых выводов:<\/p>\n<ol start=\"1\">\n<li><b>Стратегическая зрелость:<\/b> Переход на собственный движок (`SeaTunnel Engine`) — это признак зрелости проекта. Команда осознала, что зависимость от универсальных, но тяжеловесных движков (Spark\/Flink) является узким местом для основного сценария использования — интеграции данных. Создание специализированного движка позволяет оптимизировать производительность и снизить накладные расходы именно для этих задач.<\/li>\n<li><b>Соответствие трендам:<\/b> Этот шаг полностью соответствует общему тренду в индустрии данных — движению от монолитных, “умеющих все” платформ к более легковесным и специализированным инструментам. Для многих задач по перемещению и простой трансформации данных запуск Spark-кластера является избыточным. SeaTunnel теперь предлагает “золотую середину”.<\/li>\n<li><b>Конкурентное позиционирование:<\/b>\n<ul>\n  <li><b>Против коммерческих SaaS ETL (Fivetran, Airbyte):<\/b> SeaTunnel является мощной open-source альтернативой. Он привлекателен для компаний, которые хотят полного контроля над своей инфраструктурой, стремятся избежать зависимости от поставщика (vendor lock-in) и имеют техническую экспертизу для самостоятельного развертывания и поддержки.<\/li>\n  <li><b>Против специализированных CDC-инструментов (Debezium):<\/b> SeaTunnel не просто захватывает изменения (CDC), а встраивает эту функциональность в полноценный конвейер интеграции. Это решение “все в одном”, которое позволяет не только извлечь данные, но и доставить их в целевую систему (например, озеро данных или хранилище) в рамках одного инструмента.<\/li>\n<\/ul>\n<\/li>\n<li><b>Фокус на “мультимодальности” — это задел на будущее.<\/b> Поддержка не только реляционных баз и Kafka, но и озер данных (Hudi, Iceberg) и, в перспективе, векторных баз, говорит о том, что проект нацелен на обслуживание современных стеков данных, включая аналитику в реальном времени и конвейеры для машинного обучения (MLOps).<\/li>\n<\/ol>\n<h5>Рекомендации<\/h5>\n<p>Исходя из этого, можно дать следующие рекомендации:<\/p>\n<ol start=\"1\">\n<li><b>Кому стоит обратить внимание на Apache SeaTunnel:<\/b>\n<ul>\n  <li><b>Командам, для которых Spark\/Flink избыточны.<\/b> Если ваша основная задача — это синхронизация данных между различными источниками (например, из MySQL в ClickHouse или из Kafka в HDFS) без сложных вычислений, `SeaTunnel Engine` может оказаться значительно более эффективным и простым в эксплуатации решением.<\/li>\n  <li><b>Компаниям, ищущим open-source замену коммерческим ETL-инструментам.<\/b> Если у вас есть экспертиза для управления Java-приложениями и вы хотите построить гибкую, масштабируемую и экономичную платформу интеграции данных, SeaTunnel — отличный кандидат.<\/li>\n  <li><b>Пользователям экосистемы Apache.<\/b> Проект тесно интегрируется с другими популярными проектами Apache (Doris, Hudi, Flink, Spark), что делает его естественным выбором для тех, кто уже использует эти технологии.<\/li>\n  <li><b>Инженерам, которым нужна унификация.<\/b> Если вы устали поддерживать отдельные скрипты или инструменты для пакетной и потоковой обработки, SeaTunnel предлагает единый подход к обоим сценариям.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Что нужно проверить перед внедрением:<\/b>\n<ul>\n  <li><b>Экосистему коннекторов:<\/b> Самое важное — убедиться, что в SeaTunnel есть готовые, стабильные коннекторы для всех ваших источников и приемников данных. Хотя сообщество активно их добавляет, покрытие может быть не таким широким, как у коммерческих лидеров рынка.<\/li>\n  <li><b>Функциональность CDC:<\/b> Если вам нужен захват изменений в реальном времени, детально изучите поддержку вашей СУБД. Проверьте, насколько стабильно работает коннектор и какие гарантии доставки (exactly-once, at-least-once) он предоставляет.<\/li>\n  <li><b>Операционная сложность:<\/b> Несмотря на то, что SeaTunnel стал проще, это все еще open-source инструмент, требующий мониторинга, настройки и периодических обновлений. Убедитесь, что у вашей команды есть ресурсы для его поддержки.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Apache SeaTunnel трансформируется в мощный и современный инструмент, который заслуживает внимания со стороны инженеров данных. Его новое позиционирование как легковесной, унифицированной платформы делает его сильным игроком на поле интеграции данных.<\/p>\n",
            "date_published": "2025-08-17T11:32:24+03:00",
            "date_modified": "2025-08-17T11:32:43+03:00",
            "tags": [
                "big data",
                "Data",
                "Data Engineer"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-209.png",
            "_date_published_rfc2822": "Sun, 17 Aug 2025 11:32:24 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "270",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-209.png"
                ]
            }
        },
        {
            "id": "256",
            "url": "https:\/\/gavrilov.info\/all\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix\/",
            "title": "RAW Hollow – революция в управлении данными от Netflix",
            "content_html": "<p>Оригинал тут: <a href=\"https:\/\/www.rutvikbhatt.com\/raw-hollow-netflixs-in-memory-co-located-object-store-its-real-life-applications\">RAW Hollow – революция в управлении данными от Netflix<\/a><\/p>\n<p>Или тут 👉 <a href=\"https:\/\/hollow.how\/raw-hollow-sigmod.pdf\">https:\/\/hollow.how\/raw-hollow-sigmod.pdf<\/a><\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix.png\" width=\"1536\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<h3>Пояснения для тех, кто не знаком с темой<\/h3>\n<p>Представьте, что Netflix — это огромный магазин, который показывает фильмы и сериалы миллионам людей по всему миру. Чтобы этот магазин работал быстро и без сбоев, ему нужно хранить и мгновенно выдавать огромное количество информации: кто что смотрит, какие фильмы доступны, какую обложку показывать, какие настройки у пользователя и так далее.<\/p>\n<p>Традиционные методы хранения данных (базы данных) бывают медленными, когда нужно получать данные очень-очень быстро, или сложными, когда их очень много и они постоянно меняются. Например, когда вы заходите посмотреть что-то, Netflix должен мгновенно понять, что вам показать на основе ваших предпочтений и доступного контента. Обычные базы данных могут не справляться с такой скоростью и объемом запросов.<\/p>\n<ul>\n<li><b>Распределенные системы:<\/b> Это означает, что Netflix не использует один огромный компьютер. Вместо этого у них тысячи маленьких компьютеров (серверов), расположенных в разных точках мира, которые работают вместе, чтобы обеспечить бесперебойный сервис.<\/li>\n<li><b>In-Memory:<\/b> “В памяти” означает, что данные хранятся прямо в оперативной памяти сервера (как в вашем компьютере, когда вы запускаете программы), а не на медленном жестком диске. Это делает доступ к данным <b><i>невероятно быстрым<\/i><\/b>.<\/li>\n<li><b>Co-Located:<\/b> “Совместно размещенный” означает, что данные хранятся на том же самом сервере, где работает программа, которой эти данные нужны. Не нужно отправлять запрос по сети на другой сервер, чтобы получить данные, что <b><i>экономит время<\/i><\/b>.<\/li>\n<li><b>Object Store:<\/b> Это не традиционная реляционная база данных с таблицами. Вместо этого данные хранятся как объекты (подобно файлам или записям), что более <b><i>гибко<\/i><\/b>.<\/li>\n<li><b>Hollow (оригинальный):<\/b> Это была технология Netflix для очень быстрого чтения данных. Она позволяла хранить целые каталоги данных в памяти для моментального доступа, но не позволяла изменять эти данные. Представьте, что это очень быстрая, но только для чтения, копия огромной книги.<\/li>\n<li><b>RAW Hollow (Read After Write Hollow):<\/b> Это развитие Hollow. Теперь можно не только читать, но и <b><i>записывать данные<\/i><\/b>, сохраняя при этом молниеносную скорость. Добавлена возможность изменять “книгу”, причем изменения мгновенно становятся видны другим, а система гарантирует, что данные не потеряются.<\/li>\n<li><b>CAP Theorem:<\/b> Это фундаментальная концепция в распределенных системах. Она утверждает, что из трех свойств – согласованность (Consistency), доступность (Availability), устойчивость к разделению (Partition tolerance) – можно одновременно гарантировать только два. Netflix же, благодаря RAW Hollow, предлагает <b><i>гибкость в выборе<\/i><\/b>: можно работать в режиме максимальной доступности (AP), где данные становятся согласованными со временем, или в режиме максимальной согласованности (CP), где данные всегда актуальны, но могут быть короткие задержки.<\/li>\n<\/ul>\n<h3>Важное в статье<\/h3>\n<ol start=\"1\">\n<li><b>Проблема, которую решает RAW Hollow:<\/b> Традиционные базы данных страдают от непредсказуемой производительности, сложности синхронизации кэшей и накладных расходов сети. RAW Hollow решает эти проблемы, предоставляя <b><i>сверхбыстрый доступ к данным<\/i><\/b> (микросекунды для чтения) за счет их хранения в памяти непосредственно в приложении.<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Эволюция от Hollow:<\/b> RAW Hollow является развитием уже зарекомендовавшей себя технологии Hollow, которая использовалась Netflix более <s>10 лет<\/s> как кеш *только для чтения*. Новая версия добавляет возможность записи и гарантии атомарности и согласованности.<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Архитектура RAW Hollow:<\/b>\n<ul>\n  <li><b>Writers (Записывающие):<\/b> Точка входа для всех операций записи. Используют Zookeeper для выбора лидера и синхронную репликацию для обеспечения долговечности данных. Способны обрабатывать до 1000 записей в секунду с нагрузкой 10 КБ.<\/li>\n  <li><b>Logkeepers (Хранители логов):<\/b> Простая, но надежная инфраструктура для долговечности. В памяти хранят циклический лог, обеспечивая быструю фиксацию записей. Высокая отказоустойчивость за счет развертывания в нескольких зонах доступности AWS.<\/li>\n  <li><b>Producers (Производители):<\/b> Синхронизируют данные из Logkeepers и распространяют их через внутренний паб\/саб сервис Netflix (Gutenberg) на Writers и Local Clients. Создают снимки данных каждые 30 секунд для долгосрочного хранения в <a href=\"https:\/\/aws.amazon.com\/s3\/\">S3<\/a>, что обеспечивает <a href=\"https:\/\/golem.ph.utexas.edu\/~distler\/maruku\/markdown_syntax.html\">надежность на уровне “11 девяток”<\/a>.<\/li>\n  <li><b>Local Clients (Локальные клиенты):<\/b> <b><i>Самая уникальная особенность<\/i><\/b>. Каждое приложение-клиент поддерживает полную, материализованную копию всего набора данных в своей памяти. Это позволяет осуществлять операции чтения без сетевых задержек (микросекунды). Получают обновления в реальном времени от Logkeepers.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-1.png\" width=\"1800\" height=\"1400\" alt=\"\" \/>\n<\/div>\n<ol start=\"4\">\n<li><b>Свойства ACID и согласованность:<\/b>\n<ul>\n  <li><b>Атомарность:<\/b> Гарантируется через API Bulk Update, где все операции в транзакции либо выполняются полностью, либо не выполняются вовсе.<\/li>\n  <li><b>Согласованность:<\/b> Поддерживается за счет всесторонней валидации схемы. API Conditional Bulk Update позволяет применять предварительные условия для предотвращения состояний гонки.<\/li>\n  <li><b>Изоляция:<\/b> Реализован уровень Read Committed, предотвращающий “грязные” чтения.<\/li>\n  <li><b>Долговечность:<\/b> Обеспечивается синхронной репликацией на Logkeepers и регулярными снимками в S3.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"5\">\n<li><b>Гибкость модели согласованности (CAP Theorem):<\/b>\n<ul>\n  <li><b>Eventually Consistent (AP-система по умолчанию):<\/b> Приоритет доступности и отказоустойчивости. Чтения мгновенны, обновления распространяются быстро, но временные несоответствия могут быть (идеально для рекомендаций).<\/li>\n  <li><b>Strong Consistency (CP-система по запросу):<\/b> Позволяет запрашивать сильную согласованность для отдельных операций. Клиент временно синхронизируется с последними изменениями. Это позволяет достичь баланса между производительностью и точностью данных для критически важных операций (например, финансовые транзакции).<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-2.png\" width=\"1536\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<ol start=\"6\">\n<li><b>Производительность и масштабируемость:<\/b>\n<ul>\n  <li><b>Чтение:<\/b> Микросекунды, так как данные “co-located”.<\/li>\n  <li><b>Запись:<\/b> До 1000 записей\/сек (10 КБ полезной нагрузки), задержка распространения обновлений — миллисекунды.<\/li>\n  <li><b>Масштаб данных:<\/b> До 100 миллионов записей на сущность, благодаря эффективному сжатию.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"7\">\n<li><b>Применение в реальном мире:<\/b> RAW Hollow уже активно используется в более чем 160 критически важных сервисах Netflix (Tier-0), включая:\n<ul>\n  <li>Управление метаданными видео (каталоги контента).<\/li>\n  <li>Системы рекомендаций и персонализации.<\/li>\n  <li>Управление сетевой инфраструктурой CDN (Open Connect).<\/li>\n  <li>Управление идентификацией и доступом (OneID).<\/li>\n  <li>Потенциал для игр, финансовых услуг (рыночные данные, борьба с мошенничеством), электронной коммерции.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-3.png\" width=\"1536\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<ol start=\"8\">\n<li><b>Операционная готовность:<\/b> Наличие инструментов мониторинга, отслеживания изменений, возможность “нулевого копирования” для окружений и быстрого отката версий.<\/li>\n<\/ol>\n<p>---<\/p>\n<h3>Вывод ИИ<\/h3>\n<p>RAW Hollow от Netflix представляет собой <b><i>парадигмальный сдвиг<\/i><\/b> в проектировании высокопроизводительных, распределенных систем управления данными для сценариев с малым и средним объемом данных. Он демонстрирует, как глубокое понимание компромиссов CAP-теоремы и инновационный подход к ко-локации данных в памяти могут обеспечить беспрецедентную комбинацию экстремально низкой задержки чтения, высокой доступности и гибко настраиваемой согласованности. Эта технология является эталоном для создания отказоустойчивых и масштабируемых микросервисов, особенно в условиях, где традиционные базы данных становятся узким местом. Успешное развертывание в критически важных сервисах Netflix подтверждает зрелость и применимость подхода RAW Hollow в реальных производственных средах. Это не просто инструмент, а <b><i>архитектурный паттерн<\/i><\/b>, который будет влиять на будущее распределенных систем.<\/p>\n<p>---<\/p>\n<h3>Шаги по применению (для внедрения аналогичного подхода)<\/h3>\n<p>Внедрение системы, подобной RAW Hollow, требует <b><i>глубокой экспертизы<\/i><\/b> в распределенных системах и серьезных инженерных ресурсов. Вот шаги, которые должны предпринять компании, сталкивающиеся с аналогичными проблемами:<\/p>\n<ol start=\"1\">\n<li><b>Анализ требований и выявление “боли”:<\/b>\n<ul>\n  <li>Определите, какие ваши сервисы страдают от высокой задержки чтения, непредсказуемой производительности баз данных или сложностей с синхронизацией кэшей.<\/li>\n  <li>Оцените, укладываются ли ваши наборы данных в категории “малые” или “средние” (помещаются ли в оперативную память). Слишком большие dataset’ы не подходят для RAW Hollow-подобных решений.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Исследование существующих решений:<\/b>\n<ul>\n  <li>Прежде чем разрабатывать что-то свое, изучите готовые ин-мемори базы данных (Redis, Apache Ignite, GemFire\/Pivotal CloudFoundry Data Services) и распределенные кэши. Hollow\/RAW Hollow — это более низкоуровневое и кастомизированное решение.<\/li>\n  <li>Оцените возможность использования Apache Kafka или подобных систем для потоковой обработки изменений, как это делает Netflix.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Проектирование архитектуры:<\/b>\n<ul>\n  <li><b>Модель данных:<\/b> Разработайте оптимальную схему данных, которая будет эффективно храниться в памяти и обеспечивать быстрый доступ. Учитывайте возможности сжатия и индексирования.<\/li>\n  <li><b>Модель согласованности:<\/b> Для каждого компонента или операции четко определите требуемый уровень согласованности (сильная или конечная). Это <b><i>критический шаг<\/i><\/b>.<\/li>\n  <li><b>Компоненты:<\/b> Определите необходимые компоненты, аналогичные Writers, Logkeepers, Producers и Local Clients.\n<ul>\n    <li><i>Writers:<\/i> Как будут приниматься и обрабатываться запросы на запись? Нужен ли механизм выбора лидера?<\/li>\n    <li><i>Durability Layer:<\/i> Как будет обеспечиваться долговечность данных? Локальные логи? Репликация? Архивация в <a href=\"https:\/\/www.w3.org\/TR\/2016\/REC-html51-20161101\/single-page.html\">S3<\/a>-подобные хранилища?<\/li>\n    <li><i>Change Propagation:<\/i> Как изменения будут распространяться между узлами и клиентами? Нужен эффективный механизм паб\/саб.<\/li>\n    <li><i>Local Data Stores:<\/i> Как данные будут храниться в памяти клиентов\/сервисов? Как будут обновляться?<\/li>\n  <\/ul>\n<\/li>\n  <li><b>Отказоустойчивость:<\/b> Разработайте механизмы для обработки сбоев отдельных компонентов (например, падение Writer, Logkeeper), восстановления после сбоев и обеспечения непрерывной работы.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Выбор технологий и инструментов:<\/b>\n<ul>\n  <li><b>Для координации:<\/b> Zookeeper или Consul для выбора лидера и управления распределенным состоянием.<\/li>\n  <li><b>Для потоковой обработки\/паб\/саб:<\/b> Kafka, Pulsar или Kinesis.<\/li>\n  <li><b>Для хранения снимков:<\/b> S3-совместимые хранилища.<\/li>\n  <li><b>Для in-memory хранения:<\/b> Возможно, придется использовать кастомные структуры данных или библиотеки для работы с памятью в выбранном языке программирования (например, Java ByteBuffer для эффективного управления памятью).<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"5\">\n<li><b>Разработка и реализация PoC (Proof of Concept):<\/b>\n<ul>\n  <li>Начните с небольшой, изолированной PoC, чтобы проверить ключевые концепции: co-located storage, запись, распространение изменений, согласованность.<\/li>\n  <li>Измерьте производительность и задержку на ранних этапах.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"6\">\n<li><b>Тестирование и оптимизация:<\/b>\n<ul>\n  <li><b>Нагрузочное тестирование:<\/b> Проверьте систему под высокой нагрузкой чтения и записи.<\/li>\n  <li><b>Chaos Engineering:<\/b> Внедряйте контролируемые сбои (как Netflix с Chaos Monkey), чтобы убедиться в устойчивости системы.<\/li>\n  <li><b>Мониторинг:<\/b> Встройте комплексные системы мониторинга и логирования для отслеживания состояния, производительности и проблемных мест во всех компонентах.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"7\">\n<li><b>Развертывание и эксплуатация:<\/b>\n<ul>\n  <li>Постепенное развертывание в производственной среде, начиная с менее критичных сервисов.<\/li>\n  <li>Обеспечение операционных процедур: обновление, резервное копирование, восстановление, масштабирование.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>В конечном итоге, использование или вдохновение RAW Hollow подходит тем, кто хочет получить сверхвысокую производительность чтения данных, сопоставимую с локальным доступом к памяти, при этом работая с распределенными системами и умеренными объемами данных, и готов к более сложной архитектуре по сравнению с использованием готовых баз данных.<\/p>\n",
            "date_published": "2025-07-30T00:08:12+03:00",
            "date_modified": "2025-09-25T16:13:48+03:00",
            "tags": [
                "big data",
                "Data",
                "Programming"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix.png",
            "_date_published_rfc2822": "Wed, 30 Jul 2025 00:08:12 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "256",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix.png",
                    "https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-1.png",
                    "https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-2.png",
                    "https:\/\/gavrilov.info\/pictures\/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-3.png"
                ]
            }
        },
        {
            "id": "252",
            "url": "https:\/\/gavrilov.info\/all\/iceberg-v-trino-puteshestvie-po-variantam-hraneniya-szhatiya-i-k\/",
            "title": "Iceberg в Trino: Путешествие по Вариантам Хранения, Сжатия и Конфигурации для Оптимальной Производительности",
            "content_html": "<p>Iceberg, как табличный формат, совершил революцию в управлении данными в озерах данных (data lakes), предоставив транзакционные гарантии и схематическую эволюцию для данных, хранящихся в файлах. В контексте Trino, мощного распределенного SQL-движка, Iceberg раскрывает свой потенциал, позволяя пользователям взаимодействовать с данными в озерах как с традиционными базами данных. Эта статья углубится в различные варианты хранения, сжатия и конфигурации Iceberg в Trino, рассматривая преимущества и недостатки каждого, и поможет вам сделать осознанный выбор для достижения оптимальной производительности и минимизации затрат.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-06-v-21.08.54.png\" width=\"1784\" height=\"496\" alt=\"\" \/>\n<\/div>\n<p>Автор: Gemini Flash. 2.5<\/p>\n<h3>1. Форматы Хранения (File Formats)<\/h3>\n<p>Iceberg не хранит данные сам по себе, а указывает на файлы данных, которые могут быть разных форматов. Выбор формата данных является одним из наиболее важных решений, напрямую влияющим на производительность запросов, эффективность сжатия и общую стоимость хранения.<\/p>\n<h4>a) Parquet<\/h4>\n<ul>\n<li>Описание:** Колоночный формат хранения данных, оптимизированный для аналитических запросов. Он хранит данные в колоночной ориентации, что позволяет Trino считывать только необходимые колонки во время выполнения запросов. Parquet тесно интегрирован с концепциями Iceberg, такими как использование идентификаторов полей (Field IDs) для поддержки надежной схемы эволюции.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Высокая производительность в аналитике:<\/b> За счет колоночного хранения и возможности Trino применять “push-down” предикатов, Parquet обеспечивает беспрецедентную скорость для большинства аналитических запросов, избирательно считывая только необходимые данные.<\/li>\n  <li><b>Эффективное сжатие:<\/b> Колоночная ориентация позволяет применять различные алгоритмы сжатия, оптимизированные для типов данных в каждой колонке, существенно снижая объем хранимых данных и, как следствие, затраты на хранение.<\/li>\n  <li><b>Нативная поддержка схемы эволюции Iceberg:<\/b> Iceberg использует Field IDs, которые записываются в метаданды Parquet. Это ключевой механизм, позволяющий Iceberg поддерживать эволюцию схемы (добавление, удаление, переименование колонок) без перезаписи данных и без нарушения целостности запросов.<\/li>\n  <li><b>Широкая поддержка и зрелость:<\/b> Parquet является фактическим стандартом для хранения аналитических данных в экосистеме больших данных и поддерживается всеми основными инструментами (Spark, Hive, Dremio, Athena, BigQuery, Snowflake и т.д.), обеспечивая отличную интероперабельность.<\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li><b>Неэффективен для точечных запросов (point lookups):<\/b> Для выборки одной или нескольких записей требуется считывать данные из нескольких колонок, что может быть менее эффективно, чем строковые форматы данных.<\/li>\n  <li><b>Сложность изменения данных:<\/b> Изменение отдельных записей требует перезаписи целых файлов или их частей, что является общей чертой для колоночных форматов.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> **Parquet – это формат по умолчанию и наиболее рекомендуемый выбор для таблиц Iceberg в Trino.<\/b> Он обеспечивает наилучший баланс производительности, эффективности хранения и простоты управления для большинства аналитических рабочих нагрузок.<\/li>\n<\/ul>\n<h4>b) ORC (Optimized Row Columnar)<\/h4>\n<ul>\n<li>Описание:** Ещё один колоночный формат, разработанный специально для Apache Hive. Он имеет много сходств с Parquet, включая колоночное хранение и эффективное сжатие. Документация Iceberg подтверждает, что ORC также может хранить необходимые метаданные (например, `iceberg.id`, `iceberg.required`) в атрибутах типов ORC для поддержки схемы эволюции.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Высокая производительность и эффективное сжатие:<\/b> Аналогично Parquet, ORC обеспечивает отличную производительность для аналитических запросов и эффективное сжатие.<\/li>\n  <li><b>Расширенное индексирование:<\/b> ORC часто содержит более гранулированные встроенные индексы (например, индексы позиций, Bloom-фильтры), которые могут быть полезны для некоторых специфических типов запросов.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Но Bloom-фильтры по умолчанию отключены в Trino вроде как, надо проверять этот конфиг:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Screenshot-from-2025-07-07-12-13-51.png\" width=\"1497\" height=\"672\" alt=\"\" \/>\n<\/div>\n<ul>\n<li><b>Совместимость со схемой эволюции Iceberg:<\/b> Iceberg способен адаптировать ORC-схему (даже путем изменения имен колонок) для своей ID-основанной эволюции, что делает его совместимым.<\/li>\n<li>Недостатки:**<\/li>\n<li><b>Неэффективен для точечных запросов:<\/b> Общий недостаток для всех колоночных форматов.<\/li>\n<li><b>Менее распространен как универсальный формат вне экосистемы Hive:<\/b> Хотя ORC является основным форматом для Hive, Iceberg чаще ассоциируется с Parquet как универсальным форматом хранения для Data Lake. Это может потенциально означать меньшую поддержку или оптимизацию в некоторых не-Hive инструментах.<\/li>\n<li><b>Специфические моменты с отображением типов:<\/b> Как видно из <a href=\"https:\/\/iceberg.apache.org\/spec\">Iceberg documentation<\/a>, существуют нюансы с отображением типов данных (например, `timestamp` и `timestamptz`) в ORC. Может потребоваться использование дополнительных атрибутов Iceberg (таких как `iceberg.timestamp-unit`) для корректной передачи семантики.<\/li>\n<li><b>Отсутствие “шрединга” для типа `variant`:<\/b> Документация указывает, что для ORC не поддерживается “шрединг” (оптимизированное хранение) для полуструктурированного типа `variant`, что может быть ограничением для пользователей, активно работающих с такими данными.<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> Хороший выбор для аналитических рабочих нагрузок, особенно если ваша существующая инфраструктура уже использует ORC, и вы хорошо знакомы с его нюансами. Однако, для новых развертываний Iceberg, **Parquet обычно является более простым и универсальным выбором по умолчанию<\/b>.<\/li>\n<\/ul>\n<h4>c) Avro<\/h4>\n<ul>\n<li>Описание:<b> Строковый формат данных, ориентированный на быструю сериализацию и десериализацию. Avro широко используется в Apache Kafka и для передачи данных между системами. Важно отметить, что Iceberg использует Avro в качестве формата **своих внутренних файлов метаданных<\/b> (например, манифестов и метаданных таблиц), где его строковая природа и возможности сериализации очень полезны. Iceberg также описывает, как Avro <i>может быть<\/i> использован для файлов данных, включая строгие правила для отображения типов данных Avro и использование Field IDs для поддержки эволюции схемы.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Отлично подходит для сериализации и передачи данных:<\/b> Благодаря своей компактности и быстрой сериализации\/десериализации, Avro идеален для потоковой передачи.<\/li>\n  <li><b>Встроенная схема (Schema-on-Read):<\/b> Схема хранится вместе с данными, что обеспечивает совместимость. Iceberg расширяет это, добавляя Field IDs в схему Avro для robustной эволюции.<\/li>\n  <li><b>Поддержка эволюции схемы:<\/b> Iceberg, благодаря внедрению Field IDs в схемы Avro и строгим правилам для `union` (например, использование `null` для опциональных полей), способен обеспечить эволюцию схемы даже для данных, хранящихся в Avro. Это <i>технически возможно<\/i> благодаря Iceberg.<\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li><b>Крайне низкая производительность для аналитики:<\/b> <b>Это ключевой и самый серьезный недостаток Avro для аналитических рабочих нагрузок.<\/b> Для запросов требуется считывать всю строку данных, даже если нужны только некоторые колонки. Это приводит к значительному избытку I\/O, увеличивает потребность в памяти и катастрофически замедляет аналитические запросы по сравнению с колоночными форматами.<\/li>\n  <li><b>Неэффективное сжатие:<\/b> Сжатие применяется ко всей строке, а не к отдельным колонкам. Это значительно снижает коэффициент сжатия по сравнению с Parquet или ORC, что приводит к увеличению объема хранимых данных и, соответственно, затрат.<\/li>\n  <li><b>Отсутствие “шрединга” для типа `variant`:<\/b> Как и в ORC, Avro не поддерживает “шрединг” для полуструктурированного типа `variant`, что может ограничивать работу со сложными схемами.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> **Категорически не рекомендуется использовать Avro в качестве формата хранения <s>данных<\/s> для таблиц Iceberg, предназначенных для аналитических запросов в Trino.<\/b> Несмотря на то, что Iceberg <i>может<\/i> технически поддерживать его для данных, это приведет к серьезному ухудшению производительности и увеличению затрат. Avro прекрасно подходит для файлов метаданных Iceberg и для потоковых данных, но не для аналитического хранения.<\/li>\n<\/ul>\n<h3>2. Алгоритмы Сжатия (Compression Algorithms)<\/h3>\n<p>Выбор алгоритма сжатия напрямую влияет на размер хранимых данных, скорость чтения\/записи и потребление ресурсов CPU. Trino поддерживает различные алгоритмы сжатия для файлов Parquet и ORC.<\/p>\n<h4>a) Snappy<\/h4>\n<ul>\n<li>Описание:** Высокоскоростной алгоритм сжатия, разработанный Google. Он оптимизирован для скорости сжатия и декомпрессии, а не для максимальной степени сжатия.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Очень быстрая декомпрессия:<\/b> Минимальное влияние на производительность запросов, что критично для активных аналитических систем.<\/li>\n  <li><b>Сбалансированное соотношение сжатия:<\/b> Обеспечивает хорошее сокращение размера файла без значительных затрат CPU.<\/li>\n  <li><b>Широкая поддержка:<\/b> Один из наиболее часто используемых алгоритмов сжатия в экосистеме big data.<\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li><b>Менее эффективное сжатие:<\/b> По сравнению с алгоритмами, ориентированными на максимальное сжатие (например, ZSTD), Snappy может занимать больше места на диске.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> **Отличный выбор по умолчанию для большинства рабочих нагрузок<\/b>, где скорость чтения является приоритетом, а степень сжатия “достаточно хороша”.<\/li>\n<\/ul>\n<h4>b) ZSTD<\/h4>\n<ul>\n<li>Описание:** Алгоритм сжатия, разработанный Facebook, предлагающий значительно лучшую степень сжатия, чем Snappy, при сохранении приемлемой скорости сжатия\/декомпрессии.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Высокая степень сжатия:<\/b> Заметно сокращает объем данных на диске, что приводит к значительной экономии затрат на хранение и уменьшению объема передаваемых данных (IO).<\/li>\n  <li><b>Хорошая скорость декомпрессии:<\/b> Хотя и медленнее, чем Snappy, ZSTD всё ещё очень быстр, особенно по сравнению с GZIP, что делает его пригодным для аналитических нагрузок.<\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li><b>Более высокое использование CPU:<\/b> Процесс сжатия и декомпрессии требует больше ресурсов CPU, чем Snappy, что может немного увеличить нагрузку на вычислительные кластеры.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> Рекомендуется, когда **снижение затрат на хранение является приоритетом<\/b>, и вы готовы пожертвовать небольшой частью производительности CPU. Отличный выбор для архивных данных или данных с высоким коэффициентом повторения.<\/li>\n<\/ul>\n<p>Trino использует кстати уровень 3 и его поменять пока нельзя :(<\/p>\n<p><a href=\"https:\/\/github.com\/airlift\/aircompressor\/blob\/3210eb16a5ec40089398c40f40ad1d177228b414\/src\/main\/java\/io\/airlift\/compress\/zstd\/CompressionParameters.java#L26\">https:\/\/github.com\/airlift\/aircompressor\/blob\/3210eb16a5ec40089398c40f40ad1d177228b414\/src\/main\/java\/io\/airlift\/compress\/zstd\/CompressionParameters.java#L26<\/a><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">public static final int DEFAULT_COMPRESSION_LEVEL = 3;<\/code><\/pre><h4>c) GZIP<\/h4>\n<ul>\n<li>Описание:** Широко распространенный и очень эффективный алгоритм сжатия.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Очень высокая степень сжатия:<\/b> Обеспечивает максимальное уменьшение размера файла, что идеально для архивирования.<\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li><b>Очень медленная декомпрессия:<\/b> Существенно замедляет операции чтения запросов, что делает его непригодным для интерактивной аналитики.<\/li>\n  <li><b>Высокое использование CPU:<\/b> значительно увеличивает нагрузку на CPU при сжатии и декомпрессии.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:<b> **Категорически не рекомендуется для активных аналитических данных в Iceberg.<\/b> Его использование оправдано только для долгосрочного архивирования, где данные редко запрашиваются, а максимальное сжатие является единственным приоритетом. Для активных данных он значительно ухудшит производительность Trino.<\/li>\n<\/ul>\n<h4>d) LZ4<\/h4>\n<ul>\n<li>Описание:** Еще один очень быстрый алгоритм сжатия, схожий по производительности со Snappy, но иногда предлагающий чуть лучшее сжатие.<\/li>\n<li>Преимущества:**\n<ul>\n  <li><b>Очень высокая скорость:<\/b> Схож со Snappy.<\/li>\n  <li><b>Хорошее соотношение сжатия.<\/b><\/li>\n<\/ul>\n<\/li>\n<li>Недостатки:**\n<ul>\n  <li>Схож со Snappy.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Использование:** Альтернатива Snappy, если требуется очень высокая скорость и хорошее сжатие.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-06-v-23.42.06.png\" width=\"1714\" height=\"1126\" alt=\"\" \/>\n<\/div>\n<h3>3. Конфигурация Iceberg в Trino<\/h3>\n<p>Правильная настройка Iceberg в Trino включает в себя конфигурацию каталога и параметров создания самих таблиц.<\/p>\n<h4>a) Конфигурация Каталога (Catalog Configuration)<\/h4>\n<p>В файле `etc\/catalog\/<catalog_name>.properties` (например, `etc\/catalog\/iceberg.properties`) вы настраиваете, как Trino будет подключаться к Iceberg и где будут храниться метаданные таблиц.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">connector.name=iceberg\niceberg.catalog.type=hive_metastore # или rest, hadoop\nhive.metastore.uri=thrift:\/\/namenode:9083 # Если hive_metastore\n# Для объектного хранилища (например, S3, MinIO)\niceberg.s3.endpoint-url=http:\/\/s3.local:9000 \niceberg.s3.region=us-east-1\niceberg.s3.access-key=YOUR_ACCESS_KEY\niceberg.s3.secret-key=YOUR_SECRET_KEY\niceberg.s3.path-style-access=true # Для некоторых S3-совместимых хранилищ<\/code><\/pre><ul>\n<li>`connector.name=iceberg`: Определяет, что используется коннектор Iceberg.<\/li>\n<li>`iceberg.catalog.type`: Определяет, какой бэкенд каталога Iceberg будет использоваться для хранения метаданных (схемы таблиц, версий и расположения файлов данных).\n<ul>\n  <li>`hive_metastore`: Использует существующий Hive Metastore. Это самый распространенный вариант, если у вас уже есть Hive Metastore.<\/li>\n  <li>`rest`: Подключается к Iceberg REST Catalog (требует развертывания отдельного сервиса). Предоставляет более чистый API и может обеспечивать лучшую производительность для операций с каталогом.<\/li>\n  <li>`hadoop`: Использует HDFS для хранения метаданных Iceberg. Менее распространен для продакшн-развертываний.<\/li>\n<\/ul>\n<\/li>\n<li>Параметры хранилища данных (Data Storage):** Независимо от типа каталога, фактические файлы данных Iceberg могут храниться в S3, HDFS, Google Cloud Storage, Azure Blob Storage и т.д. Вам нужно настроить соответствующие параметры в конфигурации каталога Trino для доступа к этому хранилищу (например, `iceberg.s3.endpoint-url`, `iceberg.s3.access-key` для S3).<\/li>\n<\/ul>\n<h4>b) Конфигурация Таблиц (Table Configuration)<\/h4>\n<p>При создании таблиц Iceberg в Trino вы можете указывать различные параметры через секцию `WITH`. Это позволяет точно настроить, как Iceberg будет хранить данные.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">CREATE TABLE my_iceberg_table (\n    id INT,\n    name VARCHAR,\n    event_timestamp TIMESTAMP(6) WITH TIME ZONE,\n    data_json VARCHAR -- Пример для хранения полуструктурированных данных\n)\nWITH (\n    format = 'PARQUET', -- Формат файлов данных\n    partitioning = ARRAY['WEEK(event_timestamp)', 'bucket(16, id)'], -- Стратегия партиционирования\n    format_version = 2, -- Версия формата Iceberg (рекомендуется 2)\n    parquet_compression = 'ZSTD', -- Алгоритм сжатия Parquet\n    parquet_row_group_size = '256MB', -- Целевой размер группы строк в Parquet\n    write_target_data_file_size_bytes = '536870912', -- ~512MB, Целевой размер файлов данных, записываемых Iceberg\n    vacuum_max_snapshots_to_keep = 10, -- Количество последних снимков для хранения\n    expire_snapshots_min_retention_ms = 86400000 -- Минимальное время удержания снимков (24 часа)\n);<\/code><\/pre><ul>\n<li>`format`: Определяет формат файла данных (`’PARQUET’` или `’ORC’`). <b>По умолчанию Iceberg использует Parquet.<\/b><\/li>\n<li>`partitioning`: Определяет стратегию партиционирования данных. Это <b>критически важно для производительности запросов<\/b>, так как Trino может пропускать целые партиции, не соответствующие условиям фильтрации. Примеры: `ARRAY[‘year(column_name)’, ‘month(column_name)’]` для временных данных, `ARRAY[‘bucket(N, column_name)’]` для равномерного распределения данных на основе хеша.<\/li>\n<li>`format_version`: Версия формата Iceberg (текущие версии 1 или 2). <b>Рекомендуется использовать `2` для новых таблиц<\/b>, так как она предлагает больше возможностей (например, поддержка удаления строк, более гибкие индексы, поддержку Positional Deletes).<\/li>\n<li>`parquet_compression`: Указывает алгоритм сжатия для Parquet файлов (`’SNAPPY’`, `’ZSTD’`, `’GZIP’`, `’LZ4’`).<\/li>\n<li>`parquet_row_group_size`: Целевой размер группы строк (row group) в Parquet файле. Рекомендуемый диапазон обычно составляет от 128MB до 512MB. Большие группы строк могут улучшить сжатие и эффективность IO, но могут замедлить запись.<\/li>\n<li>`parquet_page_size`: Размер страницы в пределах группы строк Parquet. Обычно не требует частых изменений, но может влиять на сжатие и гранулярность доступа к данным.<\/li>\n<li>`write_target_data_file_size_bytes`: <b>Очень важный параметр.<\/b> Определяет целевой размер файлов данных, которые Iceberg будет записывать. Хороший диапазон — от 128 МБ до 1 ГБ (~134217728 до 1073741824 байт). Чрезмерно маленькие файлы приводят к “проблеме маленьких файлов” (Small File Problem), что увеличивает нагрузку на метаданные и замедляет запросы. Чрезмерно большие файлы могут снизить параллелизм чтения.<\/li>\n<li>`vacuum_max_snapshots_to_keep`: Количество последних снимков таблицы, которые Iceberg должен сохранять. Важно для операций `VACUUM` и возможности откатывать таблицу к предыдущим состояниям.<\/li>\n<li>`expire_snapshots_min_retention_ms`: Минимальное время удержания снимков (в миллисекундах) до их удаления.<\/li>\n<\/ul>\n<h3>Подведение Итога<\/h3>\n<p>Выбор правильных форматов, сжатия и конфигурации для Iceberg в Trino является решающим для оптимизации производительности, стоимости и управляемости вашего озера данных.<\/p>\n<ul>\n<li>Формат Хранения:**\n<ul>\n  <li><b>Parquet:<\/b> Явно превосходит для большинства аналитических рабочих нагрузок. Колоночная природа, эффективное сжатие, нативная интеграция Field IDs Iceberg для схемы эволюции и широкая поддержка делают его <b>выбором по умолчанию и наиболее рекомендуемым.<\/b><\/li>\n  <li><b>ORC:<\/b> Достойная альтернатива Parquet, особенно если ваша инфраструктура уже использует ORC. Однако, учитывая нюансы отображения типов и общий тренд, Parquet часто является предрочтительнее для новых проектов.<\/li>\n  <li><b>Avro:<\/b> <b>Категорически не подходит для хранения <s>данных<\/s> аналитических таблиц.<\/b> Несмотря на то, что Iceberg использует Avro для своих метаданных, применение его для самих данных приведет к крайне низкой производительности и высоким затратам.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Алгоритмы Сжатия:**\n<ul>\n  <li><b>Snappy:<\/b> Отличный компромисс между скоростью и степенью сжатия. Хорош для большинства активных данных, где скорость доступа критична.<\/li>\n  <li><b>ZSTD:<\/b> Предпочтителен, если снижение затрат на хранение является приоритетом, и вы готовы к небольшому увеличению использования CPU. Начинает обгонять Snappy по популярности для многих сценариев.<\/li>\n  <li><b>GZIP:<\/b> Избегайте для активных данных из-за низкой скорости декомпрессии. Используйте только для долгосрочного архивирования.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>Конфигурация:**\n<ul>\n  <li><b>Партиционирование:<\/b> Критично для ускорения запросов. Выбирайте его с умом, основываясь на шаблонах запросов и объеме данных.<\/li>\n  <li><b>Версия формата Iceberg (v2):<\/b> Используйте для новых таблиц, чтобы получить доступ к последним возможностям.<\/li>\n  <li><b>Целевой размер файлов (`write_target_data_file_size_bytes`):<\/b> Настройте в диапазоне 128MB-1GB, чтобы избежать проблемы маленьких файлов и обеспечить хороший параллелизм Trino.<\/li>\n  <li><b>Параметры сжатия и размера блоков Parquet:<\/b> Настройте такие параметры, как `parquet_row_group_size` и `parquet_compression` для дальнейшей оптимизации.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Используя Iceberg с Trino, вы получаете мощную комбинацию для создания высокопроизводительных, надежных и управляемых озер данных. Тщательный выбор форматов хранения, алгоритмов сжатия и тонкая настройка конфигурации будут ключами к максимальному использованию потенциала этих технологий, обеспечивая оптимальную производительность запросов при контролируемых затратах. Начните с Parquet и Snappy\/ZSTD, а затем адаптируйте конфигурацию в зависимости от ваших конкретных рабочих нагрузок и требований к стоимости.<\/p>\n",
            "date_published": "2025-07-06T21:18:49+03:00",
            "date_modified": "2025-07-07T12:15:04+03:00",
            "tags": [
                "big data",
                "Iceberg"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-06-v-21.08.54.png",
            "_date_published_rfc2822": "Sun, 06 Jul 2025 21:18:49 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "252",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-06-v-21.08.54.png",
                    "https:\/\/gavrilov.info\/pictures\/Screenshot-from-2025-07-07-12-13-51.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-06-v-23.42.06.png"
                ]
            }
        },
        {
            "id": "251",
            "url": "https:\/\/gavrilov.info\/all\/sravnenie-resheniy-dlya-schema-registry-confluent-vs-apicurio\/",
            "title": "Сравнение решений для Schema Registry: Confluent vs Apicurio",
            "content_html": "<p>Schema Registry (реестр схем) — критический компонент в экосистеме Apache Kafka, обеспечивающий контракты данных, управление эволюцией схем и валидацию сообщений. В 2025 году лидирующие решения — <b>Confluent Schema Registry<\/b>, <b>Apicurio Registry<\/b>, а также облачные и интегрированные варианты (AWS Glue, Redpanda). Разберем их функциональность, преимущества и недостатки.<\/p>\n<h4><b>1. Confluent Schema Registry: эталон для Kafka<\/b><\/h4>\n<p><b>Функциональность<\/b><\/p>\n<ul>\n<li>Форматы схем** Avro, Protobuf, JSON Schema. <a href=\"https:\/\/www.confluent.io\/blog\/best-practices-for-confluent-schema-registry\/\">confluent.io<\/a><\/li>\n<li>Совместимость:** Поддерживает 8 стратегий совместимости (BACKWARD, FORWARD, FULL и их транзитивные аналоги) <a href=\"https:\/\/docs.confluent.io\/platform\/current\/schema-registry\/concepts\/avro.html#compatibility-types-for-avro-schemas\">confluent.io<\/a> с проверкой при регистрации новой версии схемы.<\/li>\n<li>Интеграции:** Глубоко встроен в Confluent Platform (Kafka Connect, ksqlDB), предоставляет REST API, а Confluent Control Center (GUI) доступен в Enterprise-версии.<\/li>\n<li>Архитектура:** Является отдельным сервисом, хранит схемы в специальном внутреннем топике Kafka (`_schemas`). Обеспечивается высокая доступность через primary-secondary узлы.<\/li>\n<\/ul>\n<p><b>Преимущества:<\/b><\/p>\n<ul>\n<li>Зрелость:** Промышленный стандарт с 2015 года, обладающий богатой документацией и обширным сообществом.<\/li>\n<li>Расширенные функции:** Включает такие возможности, как Schema Linking (репликация и синхронизация схем между различными кластерами Schema Registry) и контексты схем для поддержки мультитенантности.<\/li>\n<li>Эффективное кэширование:** Клиенты запрашивают схему из кэша по ID (который передается в сообщении), значительно уменьшая накладные расходы.<\/li>\n<\/ul>\n<p><b>Недостатки:<\/b><\/p>\n<ul>\n<li>Операционные затраты:** Требует отдельного развертывания, мониторинга и управления инфраструктурой, если не используется управляемый сервис.<\/li>\n<li>Стоимость:** Расширенные функции, включая Enterprise GUI и усиленную безопасность, доступны только в платных версиях Confluent Platform.<\/li>\n<\/ul>\n<h4><b>2. Apicurio Registry: гибкость open source<\/b><\/h4>\n<p><b>Функциональность:<\/b><\/p>\n<ul>\n<li>Форматы схем:** Поддерживает не только Avro, Protobuf и JSON Schema, но и другие форматы, такие как OpenAPI, AsyncAPI, GraphQL и XML Schema.<a href=\"https:\/\/www.apicur.io\/registry\/docs\/apicurio-registry\/3.0.x\/assets-attachments\/registry-rest-api.htm\">apicur.io<\/a><\/li>\n<li>Совместимость:** Предоставляет правила валидации и совместимости, включая возможность определения кастомных правил.<\/li>\n<li>Хранение:** Обладает плагинной архитектурой для Persistent Storage, поддерживая Kafka, PostgreSQL, Infinispan и in-memory хранилище.<\/li>\n<li>Интеграции:** Имеет REST API, удобную веб-консоль для управления, Kafka SerDes (сериализаторы\/десериализаторы) и совместим с клиентами Confluent. <a href=\"https:\/\/www.apicur.io\/registry\/docs\/apicurio-registry\/3.0.x\/getting-started\/assembly-intro-to-the-registry.html\">apicur.io<\/a><\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"2560\" data-ratio=\"2.2918531781558\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.30.16.png.jpg\" width=\"2560\" height=\"1117\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.30.06.png.jpg\" width=\"2560\" height=\"1285\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.41.png.jpg\" width=\"2560\" height=\"1548\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.27.png.jpg\" width=\"2560\" height=\"1072\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.11.png.jpg\" width=\"2560\" height=\"1574\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.00.png.jpg\" width=\"2560\" height=\"978\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.28.50.png.jpg\" width=\"2560\" height=\"921\" alt=\"\" \/>\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.28.37.png.jpg\" width=\"2560\" height=\"1201\" alt=\"\" \/>\n<\/div>\n<\/div>\n<p><b>Преимущества:<\/b><\/p>\n<ul>\n<li>Гибкость:** Поддержка более 10 форматов спецификаций и возможность выбора СУБД для хранения данных.<\/li>\n<li>Без vendor lock-in:** Полностью open source, распространяется под лицензией Apache 2.0.<\/li>\n<li>Безопасность:** Интеграция с Keycloak (OpenID Connect) для управления доступом предоставляется бесплатно.<\/li>\n<\/ul>\n<p><b>Недостатки:<\/b><\/p>\n<ul>\n<li>Сложность эксплуатации:** Отсутствие официальной managed-версии означает, что для развертывания и поддержания Apicurio Registry требуются собственные навыки администрирования.<\/li>\n<li>Ограниченная зрелость:** По сравнению с Confluent, может иметь меньше встроенных инструментов мониторинга и интеграций с другими корпоративными системами, хотя быстро развивается. Но за Confluent надо платить.<\/li>\n<\/ul>\n<h4><b>3. Альтернативные решения<\/b><\/h4>\n<h5><b>AWS Glue Schema Registry<\/b><\/h5>\n<ul>\n<li>Плюсы:** Serverless-сервис, глубокая интеграция с другими сервисами AWS (такими как Amazon MSK и Kinesis), модель оплаты по запросам.<\/li>\n<li>Минусы:** Замкнут в экосистеме AWS, может не поддерживать все продвинутые правила совместимости (например, транзитивные).<\/li>\n<\/ul>\n<h5><b>Redpanda Schema Registry<\/b><\/h5>\n<ul>\n<li>Плюсы:** Встроен непосредственно в брокер сообщений Redpanda, что обеспечивает очень низкую задержку и API-совместимость с Confluent Schema Registry.<\/li>\n<li>Минусы:** Привязка к брокеру Redpanda, относительно меньше enterprise-функций по сравнению с Confluent.<\/li>\n<\/ul>\n<h4><b>Сравнительная таблица<\/b><\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\"><b>Критерий<\/b><\/td>\n<td style=\"text-align: center\"><b>Confluent<\/b><\/td>\n<td style=\"text-align: center\"><b>Apicurio<\/b><\/td>\n<td style=\"text-align: center\"><b>AWS Glue<\/b><\/td>\n<td style=\"text-align: center\"><b>Redpanda<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Основные форматы схем<\/b><\/td>\n<td style=\"text-align: center\">Avro, Protobuf, JSON<\/td>\n<td style=\"text-align: center\">Avro, Protobuf, JSON, OpenAPI, AsyncAPI, GraphQL, XML<\/td>\n<td style=\"text-align: center\">Avro, Protobuf, JSON<\/td>\n<td style=\"text-align: center\">Avro, Protobuf, JSON<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right\"><b>Стратегии совместимости<\/b><\/td>\n<td style=\"text-align: center\">8 типов (включая транзитивные)<\/td>\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\">Отдельный сервис<\/td>\n<td style=\"text-align: center\">Плагинное хранилище (Kafka, DB)<\/td>\n<td style=\"text-align: center\">Serverless<\/td>\n<td style=\"text-align: center\">Встроен в брокер<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Managed-решение<\/b><\/td>\n<td style=\"text-align: center\">Confluent Cloud<\/td>\n<td style=\"text-align: center\">Нет<\/td>\n<td style=\"text-align: center\">Да (AWS Managed Service)<\/td>\n<td style=\"text-align: center\">Нет (брокер Redpanda может быть управляемым)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Лицензия<\/b><\/td>\n<td style=\"text-align: center\">Платные расширения, Open Core<\/td>\n<td style=\"text-align: center\">Open Source (Apache 2.0)<\/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>SLA \/ Мониторинг<\/b><\/td>\n<td style=\"text-align: center\">Enterprise-инструменты, Confluent Control Center<\/td>\n<td style=\"text-align: center\">Требует самостоятельного внедрения<\/td>\n<td style=\"text-align: center\">CloudWatch, стандарт AWS SLA<\/td>\n<td style=\"text-align: center\">Prometheus + Grafana, внутренняя телеметрия<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Веб-консоль (GUI)<\/b><\/td>\n<td style=\"text-align: center\">Confluent Control Center (платный)<\/td>\n<td style=\"text-align: center\">Встроенная веб-консоль (бесплатно)<\/td>\n<td style=\"text-align: center\">AWS Management Console<\/td>\n<td style=\"text-align: center\">Нет (через API)<\/td>\n<\/tr>\n<\/table>\n<h4><b>Итоги: что выбрать?<\/b><\/h4>\n<ol start=\"1\">\n<li><b>Confluent Schema Registry<\/b> — идеален для корпоративных Kafka-инфраструктур, где требуются максимальная стабильность, расширенное управление схемами и глубокая интеграция с Confluent Platform. Подходит для финансовых и регуляторных сценариев из-за своей зрелости и поддержки.<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Apicurio Registry<\/b> — лучший выбор для гибридных сред, микросервисов на gRPC\/GraphQL, или при ограниченном бюджете. Незаменим, если вы ищете полностью открытое и гибкое решение, которое не привязывает вас к конкретному вендору. Еще, кстати, он интегрируется с OpenMetaData – как говорят.<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Облачные решения (AWS Glue Schema Registry)<\/b> — подойдут для стека AWS, если необходимо минимизировать операционные накладные расходы и использовать полностью управляемый сервис.<\/li>\n<\/ol>\n<ol start=\"4\">\n<li><b>Интегрированные решения (Redpanda Schema Registry)<\/b> — оправданы, если вы уже используете или планируете использовать Redpanda в качестве брокера сообщений.<\/li>\n<\/ol>\n<p><b>Главный тренд 2025:<\/b> Рост популярности Apicurio из-за поддержки полиглотных архитектур и принципов open source. Однако Confluent сохраняет лидерство в Kafka-centric проектах благодаря своей глубине интеграции и богатому набору функций для крупных предприятий.<\/p>\n<blockquote>\n<p><b>Предостережение:<\/b> «Бесплатные» решения (Apicurio, Redpanda) требуют операционных затрат на развертывание, мониторинг и обслуживание. Для стартапов с ограниченным бюджетом Apicurio может быть предпочтительнее; для крупных предприятий, уже инвестировавших в Kafka, Confluent часто становится естественным выбором. Миграция между системами возможна, но требует тщательной проверки совместимости схем и данных.<\/p>\n<\/blockquote>\n<p>А у кого-то есть платная kafka?<\/p>\n",
            "date_published": "2025-07-04T23:40:13+03:00",
            "date_modified": "2025-07-23T10:16:28+03:00",
            "tags": [
                "big data",
                "Metadata"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.30.16.png.jpg",
            "_date_published_rfc2822": "Fri, 04 Jul 2025 23:40:13 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "251",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.30.16.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.30.06.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.41.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.27.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.11.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.29.00.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.28.50.png.jpg",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-07-04-v-08.28.37.png.jpg"
                ]
            }
        }
    ],
    "_e2_version": 4171,
    "_e2_ua_string": "Aegea 11.4 (v4171e)"
}