Yuriy Gavrilov

Welcome to my personal place for love, peace and happiness 🤖

🚀 Создание почтиReal-Time Data Lake: Быстрая миграция данных в Apache Iceberg или Parquet

Сегодня Gemini 3.1 Pro Preview расскажет свое мненИИе))

Связывание транзакционных баз (PostgreSQL) и аналитических хранилищ (ClickHouse) через прямые агрегации и `JOIN` часто приводит к жесточайшим блокировкам и деградации продакшена. Когда бизнес требует быстрый результат, а внедрение полноценного CDC (Debezium + Kafka) откладывается из-за сроков и сложности, лучшим решением становится пакетная и микро-пакетная выгрузка данных в озеро (в форматы Parquet и Apache Iceberg).

С точки зрения архитектуры, наша главная цель — минимизировать время загрузки данных T load и усилия инженеров на развертывание E setup. Наша целевая функция: min(T load × E setup)

В этой статье собраны исключительно рабочие, протестированные подходы для быстрой интеграции с озером данных (Data Lake) и аналитическим движком Trino.


🐘 1. Экспорт данных из PostgreSQL: Проверенные инструменты

Мы полностью исключаем создание и восстановление тяжелых дампов (`pg_dump`). Вся транзитная нагрузка ложится исключительно на асинхронные реплики.

🌟 Подход А: Движок OLake (Самый быстрый старт в Iceberg)

Для задачи “результат нужен вчера и без сложного стека” идеально подходит OLake. Это высокопроизводительный движок репликации баз данных напрямую в Apache Iceberg (или Parquet), минуя промежуточные шины сообщений.

Шаг 1. Запуск сервиса (конфигурация `docker-compose.yml`):

version: '3.8'
services:
  olake:
    image: olakeio/olake:latest
    ports:
      - "8080:8080"
    environment:
      # Настройки доступов к вашему S3/MinIO
      - AWS_ACCESS_KEY_ID=your_access_key
      - AWS_SECRET_ACCESS_KEY=your_secret_key
      - AWS_REGION=us-east-1

Шаг 2. Запуск репликации:
Вы отправляете JSON-манифест в OLake (через UI или REST API). Движок самостоятельно делает первоначальный слепок PostgreSQL (Full Load со скоростью до 580K RPS), а затем переключается на чтение инкрементов (CDC):

{
  "pipeline_name": "pg_to_iceberg_fast",
  "source": {
    "type": "postgres",
    "connection_url": "postgresql://readonly_user:password@replica_host:5432/prod_db",
    "tables": ["public.customer", "public.orders"]
  },
  "destination": {
    "type": "iceberg",
    "catalog_type": "rest",
    "catalog_uri": "http://iceberg-rest:8181",
    "warehouse_path": "s3://my-datalake/warehouse/"
  },
  "replication_mode": "full_and_cdc"
}

🐍 Подход Б: DuckDB (Легковесная скриптовая выгрузка)

Если вы хотите управлять выгрузкой через свои `cron`-задачи или Airflow, идеальным инструментом выступает аналитическая in-memory СУБД DuckDB. Ниже приведен протестированный Python-скрипт, который напрямую подключается к реплике и потоково перегоняет данные в Parquet на S3.

Рабочий скрипт на Python (`export_to_lake.py`):

import duckdb

# Открываем in-memory соединение DuckDB
con = duckdb.connect()

# 1. Устанавливаем и загружаем необходимые расширения
con.execute("INSTALL postgres;")
con.execute("INSTALL httpfs;")
con.execute("LOAD postgres;")
con.execute("LOAD httpfs;")

# 2. Настраиваем подключение к объектному хранилищу
con.execute("""
    SET s3_region='us-east-1';
    SET s3_access_key_id='YOUR_KEY';
    SET s3_secret_access_key='YOUR_SECRET';
    SET s3_endpoint='s3.your-domain.com';
""")

# 3. Подключаемся к реплике PostgreSQL
# Команда ATTACH монтирует Postgres прямо в DuckDB под именем 'pg'
con.execute("""
    ATTACH 'host=replica_host port=5432 dbname=postgres user=postgres password=password' 
    AS pg (TYPE postgres);
""")

# 4. Копируем таблицу public.customer в S3 в сжатом формате Parquet
con.execute("""
    COPY pg.public.customer
    TO 's3://my-datalake/raw/customer.parquet' 
    (FORMAT PARQUET, COMPRESSION ZSTD);
""")

print("Выгрузка в Data Lake успешно завершена!")

🖱️ 2. Унификация аналитики с ClickHouse

Данные из ClickHouse также необходимо перегружать в Озеро (для Trino), чтобы избежать дублирования логики таблиц и нагрузки на саму СУБД тяжелыми сторонними `JOIN`-ами.

🛠 Базовый подход: Нативная табличная функция S3

Самый простой и не требующий дополнительной инфраструктуры способ — использовать встроенную функцию `s3()`. Она позволяет в один SQL-запрос отправить результат выборки прямо в объектное хранилище в нужном формате.

Пример выгрузки из ClickHouse в Parquet (выполняется в `clickhouse-client`):

-- Прямая вставка данных из локальной MergeTree таблицы в файл Parquet на S3
INSERT INTO FUNCTION s3(
    'https://s3.us-east-1.amazonaws.com/my-datalake/raw/clickhouse_export/events_{_partition_id}.parquet',
    'YOUR_KEY',
    'YOUR_SECRET',
    'Parquet'
)
SELECT id, event_type, payload, event_date
FROM local_events_mergetree
WHERE event_date = today();

*Совет: Используйте макрос `{_partition_id}` в пути файла для автоматического разбиения больших выгрузок.*

🌊 Продвинутый подход: Project Antalya (ClickHouse + Iceberg)

Для построения архитектуры на десятилетие вперед разработчики из Altinity создали сборку Project Antalya. Она позволяет использовать таблицы Iceberg в S3 как *полноценное разделяемое хранилище*, работающее со скоростью локального диска, но обходящееся в 10 раз дешевле.

Пример прозрачного монтирования:

-- 1. Подключаем готовую Iceberg-таблицу прямо как движок ClickHouse
CREATE TABLE iceberg_customer
ENGINE = Iceberg('s3://my-datalake/warehouse/customer', 'aws_key', 'aws_secret');

-- 2. Запрашиваем данные. Теперь Trino и ClickHouse читают одни и те же Parquet-файлы!
SELECT count(*) FROM iceberg_customer WHERE status = 'active';

⚠️ Решение частых проблем при транзите данных (Troubleshooting)


1. Управление оперативной памятью (OOM) в DuckDB
При скриптовой выгрузке гигантских таблиц in-memory движок может исчерпать RAM сервера.
Решение: Обязательно ограничивайте ресурсы сразу после

duckdb.connect()

:

con.execute("PRAGMA memory_limit='16GB'")
con.execute("PRAGMA threads=4")


2. Консолидация сложных типов данных PostgreSQL
Если в вашей таблице есть

JSONB

,

UUID

или пользовательские массивы, Parquet может упасть с ошибкой соответствия типов.
Решение: Вместо

COPY pg.table

напишите явный SQL-запрос с приведением к строке (

::VARCHAR

):

con.execute("""
    COPY (
        SELECT id, metadata::VARCHAR AS metadata 
        FROM pg.public.customer
    )
    TO 's3://my-datalake/raw/customer.parquet' (FORMAT PARQUET);
""")

Внутри Trino эти строки легко парсятся функциями вроде

json_extract()

.


3. Защита асинхронных реплик PostgreSQL от разрывов
Длительный процесс

SELECT *

(или

COPY

) мешает мастеру применять WAL-логи на реплике (из-за очистки строк VACUUM-ом).
Решение: На аналитической реплике (в файле

postgresql.conf

) обязательно пропишите:

max_standby_streaming_delay = -1
max_standby_archive_delay = -1
hot_standby_feedback = on

Это позволит реплике “ставить на паузу” конфликтующие обновления и не обрывать ваш транзит данных.


🎯 План внедрения (Roadmap)

  1. Мгновенный результат (Первые 1-3 дня): Используйте проверенный Python-скрипт на DuckDB для баз PostgreSQL и классическую функцию `s3()` для ClickHouse. Они перенесут исторические таблицы в Parquet на S3 без внесения изменений в инфраструктуру. Trino сразу увидит эти файлы.
  2. Системный подход (1-2 недели): Разверните OLake. Потратив пару часов на конфигурацию манифестов, вы получите автоматический конвейер инкрементальной загрузки, который напрямую питает ваши Iceberg-каталоги.
  3. Объединение аналитики (2-4 недели): Начните использовать Project Antalya, чтобы обогатить озеро горячими данными ClickHouse, избегая дублирования.
  4. Окончательная эволюция: Когда бизнес-пожар потушен и аналитики получают данные в приемлемые сроки (T lag < 1 часа), вы можете спокойно внедрить **Debezium + Kafka**. Но делать это стоит только для узкого сегмента сверхкритичных таблиц, где аналитика требуется в строгом Real-Time.

Немного сборной сборки про качество и ML

Немного сборной сборки про качество и ML

https://github.com/andkret/Cookbook

https://podcast.ru/e/3Ldlf9-6ebG

https://habr.com/ru/companies/vtb/news/762384/

Полезные ресурсы и ссылки:
Курс MLOps (OTUS): https://otus.ru/lessons/ml-bigdata/
Основные идеи из книги «Сотрудничество в DevOps-культуре»: http://agilemindset.ru/основные-идеи-из-книги-сотрудничест/
MLOps: Continuous delivery and automation pipelines in machine learning: https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning
Как создавать качественные ML-системы. Часть 1: каждый проект должен начинаться с плана: https://habr.com/ru/companies/vk/articles/749850/
Как создавать качественные ML-системы. Часть 2: приручаем хаос: https://habr.com/ru/companies/vk/articles/749852/
The Data Engineering Cookbook: https://github.com/andkret/Cookbook
Стандарты:
ISO/IEC DIS 5259-1: https://www.iso.org/standard/81088.html
SO/IEC DIS 5259-4: https://www.iso.org/standard/81093.html
ISO/IEC 8183:2023: https://www.iso.org/standard/83002.html

Архитектура Client Spooling: Как быстро выгружать гигантские датасеты в Trino и Apache DataFusion

Работа с Big Data часто упирается в классическое “узкое горлышко”: кластер может обработать терабайты данных за секунды, но передача результатов (Result Set) обратно на сторону клиента (например, в Jupyter или скрипт) занимает часы. На дворе апрель 2026 года, и современные аналитические движки предлагают эффективные методы обхода этой проблемы — концепцию Spooling.

Немного душноты:

Архитектура Client Spooling в Trino создавалась с параноидальным акцентом на безопасность, в S3 выкидываются куски сырых, возможно, чувствительных данных.

Когда Trino решает сбросить данные в объектное хранилище, он всегда шифрует их на лету.
Для этого используется механизм S3 SSE-C (Server-Side Encryption with Customer-provided keys). Trino генерирует уникальный случайный AES-ключ для каждого запроса, отправляет его в MinIO вместе с данными, а клиенту (вашему Jupyter) отдает ссылку + этот же ключ для расшифровки.
Если мы используем локальный MinIO по адресу http://minio:9000 (без SSL/TLS), сервер MinIO видит, что ему пытаются передать секретный пароль (SSE-C ключ) по открытому незащищенному HTTP-каналу.
MinIO (как и настоящий AWS S3) строго запрещает это по спецификации. Он возвращает HTTP 400 Bad Request с ошибкой: “Requests specifying Server Side Encryption... must be made over a secure connection”. Поэтому тестировать лучше на реальном s3. И еще

Мгновенное удаление (Сборка мусора)

Главное правило Client Spooling: Trino удаляет файлы сразу же, как только они были прочитаны клиентом.
Как только ваш Python-скрипт или Jupyter получает ссылку на файл, скачивает его и отправляет координатору Trino HTTP-сигнал (ACK), что кусок получен, координатор дает команду немедленно удалить этот объект из S3.
Если запрос отменен или упал с ошибкой, Trino тоже моментально зачищает за собой fs.location. Вы просто не успеете их там увидеть.

Данных слишком мало (Thresholds)

Писать 10 строк в S3, генерировать для них Pre-signed URLs и отдавать клиенту — это дольше, чем просто плюнуть эти 10 строк текстом через координатор. Trino использует эвристику: если Result Set маленький, он отдается “инлайн” (внутри JSON-ответа самого координатора), и S3 не задействуется.

В этой статье мы разберем, как передавать результаты запросов через промежуточное S3-хранилище, на примере движков Trino и Apache DataFusion.

Физика проблемы и математика Spooling

В классической архитектуре все воркеры кластера отправляют вычисленные строки на главный узел (Coordinator), а тот уже отдает их по одному каналу клиенту.

Если D — это объем результирующей выборки, а B c — пропускная способность сети координатора, то время выгрузки данных клиенту без спулинга равно:

T classic = B / Dc

В режиме Spooling координатор не гоняет данные через себя. Воркеры напрямую, параллельно пишут куски результата в дешевое объектное хранилище (S3/MinIO). Клиент получает лишь ссылки на эти файлы и скачивает их напрямую. Если у нас N файлов в S3, доступных для многопоточного скачивания с пропускной способностью клиента B client: T spooling ≈ min(N×B s3,B client)D

Это позволяет ускорить выгрузку в десятки раз, так как $B_{client}$ и распределенный $B_{s3}$ обычно значительно больше ограничений одного координатора.


Подготовка минимальной инфраструктуры

Для демонстрации двух подходов мы убрали из нашего кластера все тяжелые клиентские среды (Jupyter, Spark) и оставили только “голое” ядро: хранилище S3, REST-каталог и SQL-движок.

минимальный

docker-compose.yml

version: '3.8'

services:
  minio:
    image: minio/minio:latest
    ports:
      - "19000:9000"
      - "19001:9001"
    environment:
      MINIO_ROOT_USER: "minio-root-user"
      MINIO_ROOT_PASSWORD: "minio-root-password"
    command: server /data --console-address ":9001"

  minio-setup:
    image: minio/mc:latest
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      sleep 5;
      mc alias set myminio http://minio:9000 minio-root-user minio-root-password;
      mc mb myminio/warehouse || true;
      "

  lakekeeper:
    image: dalongrong/lakekeeper:latest
    ports:
      - "8181:8181"
    environment:
      - S3_ENDPOINT=http://minio:9000
      - S3_REGION=us-east-1
      - S3_ACCESS_KEY_ID=minio-root-user
      - S3_SECRET_ACCESS_KEY=minio-root-password
    depends_on:
      - minio-setup

  trino:
    image: trinodb/trino:latest
    ports:
      - "8080:8080"

Шаг 1. Настройка каталога и генерация данных (Trino)


Сначала мы генерируем данные в Trino. Запрос

CREATE CATALOG

использует динамическое подключение к Lakekeeper REST API. Скрипт записывает файлы в формате Parquet в MinIO:

config.properties

protocol.spooling.enabled=true
# 256-битный ключ в формате base64. Вы можете сгенерировать свой с помощью команды `openssl rand -base64 32`
protocol.spooling.shared-secret-key=jxTKysfCBuMZtFqUf8UJDQ1w9ez8rynEJsJqgJf66u0=

catalog.management=dynamic

spooling-manager.properties

spooling-manager.name=filesystem
# Включаем чтение/запись в S3 для Spooling
fs.s3.enabled=true
# Путь внутри MinIO (указываем через s3://)
fs.location=s3://warehouse/client-spooling/

# Системные настройки S3 (MinIO)
s3.endpoint=http://minio:9000
s3.region=us-east-1
s3.aws-access-key=minio-root-user
s3.aws-secret-key=minio-root-password
s3.path-style-access=true

-- 1. Подключение каталога Iceberg

CREATE CATALOG test_warehouse USING iceberg
WITH (
    "iceberg.catalog.type" = 'rest',
    "iceberg.rest-catalog.uri" = 'http://lakekeeper:8181/catalog/',
    "iceberg.rest-catalog.warehouse" = '00000000-0000-0000-0000-000000000000/test_warehouse',
    "iceberg.rest-catalog.security" = 'OAUTH2',
    "iceberg.rest-catalog.nested-namespace-enabled" = 'true',
    "iceberg.rest-catalog.vended-credentials-enabled" = 'true',
    "fs.native-s3.enabled" = 'true',
    "s3.region" = 'us-east-1',
    "s3.path-style-access" = 'true',
    "s3.endpoint" = 'http://minio:9000'
);

-- 2. Создание структуры

CREATE SCHEMA test_warehouse.test_schema;

CREATE TABLE test_warehouse.test_schema.my_table (
    id BIGINT,
    data VARCHAR
) WITH (format = 'PARQUET');

-- 3. Запись данных

INSERT INTO test_warehouse.test_schema.my_table VALUES (1, 'hello'), (2, 'world');

Если написать Select – должно быть как-то так

Аналог Spooling в Apache DataFusion (Через экспорт)

Trino поддерживает протокол *Client Spooling* “из коробки” — когда Python-клиент запрашивает огромный `SELECT`, Trino сам незаметно пишет куски в S3 и отдает клиенту готовые ссылки.

В Apache DataFusion (который часто работает как локальный движок `datafusion-cli` или встраиваемая библиотка поверх S3) применяется более прозрачный паттерн делегирования (Explicit Spooling). Мы вручную инструктируем движок сохранить результаты агрегации в распределенное хранилище, чтобы позже забрать их в удобном формате — например, упаковав их в `JSON` и сжав алгоритмом `ZSTD`.

1. Подключение к S3 и маппинг исходной таблицы

Запускаем `datafusion-cli`, передав доступы как переменные среды (для предотвращения ошибок парсинга опций):

AWS_ACCESS_KEY_ID="minio-root-user" \
AWS_SECRET_ACCESS_KEY="minio-root-password" \
AWS_ENDPOINT="http://localhost:19000" \
AWS_REGION="us-east-1" \
AWS_ALLOW_HTTP="true" \
datafusion-cli

Внутри консоли подключаем директорию с Parquet-файлами, сгенерированными Trino:

CREATE EXTERNAL TABLE my_parquet_data 
STORED AS PARQUET 
LOCATION 's3://warehouse/019d81a3-c2d6-7ed2-ab15-070becf62582/my_table-13e4b91a2b4e47d98f312b1384263880/data/';
2. Массовая конвертация и выгрузка (DataFusion COPY)

Вместо того чтобы тянуть миллионы строк на локальный терминал, мы просим DataFusion выполнить преобразование и записать итог запроса обратно в MinIO.

Мы выбираем построчный JSON с экстремальным сжатием:

COPY (
    -- Тут может быть любая сложная агрегация:
    -- SELECT id, count(data) FROM my_parquet_data GROUP BY id
    SELECT * FROM my_parquet_data
) 
TO 's3://warehouse/019d81a3-c2d6-7ed2-ab15-070becf62582/my_table-13e4b91a2b4e47d98f312b1384263880/json_export/' 
STORED AS JSON
OPTIONS (
    'format.compression' 'zstd'
);

Результат:

+-------+
| count |
+-------+
| 2     |
+-------+
1 row(s) fetched. 
Elapsed 0.270 seconds.

За миллисекунды (0.270 sec) DataFusion прочитал партиции, трансформировал бинарные столбцы в текст и сжал его.

В чем преимущество подхода DataFusion?

Описанный паттерн выполнения команды `COPY TO` с сохранением `.json.zst` в MinIO полностью воспроизводит механику Spooling:

  1. Отсутствие OOM (Out Of Memory): Клиент получает только метаданные `count`, а не гигабайты сырых данных в оперативную память.
  2. Параллелизм: Если исходных файлов много, DataFusion будет писать множество потоков `part-0.json.zst`, `part-1.json.zst` в бакет параллельно.
  3. Удаленное потребление: Вы можете запустить легкий Python-скрипт (Pandas) на дешевой машине, который просто прочитает эти сжатые легковесные JSON объекты напрямую из MinIO, минуя дорогостоящие вычислительные кластеры.

Еще немного про Fault-Tolerant Execution (FTE), нужно провести важную границу между архитектурой Trino (готовый распределенный кластер) и архитектурой DataFusion (ядро/библиотека выполнения запросов).

В самом “голом” ядре DataFusion (которое вы запускаете в `datafusion-cli` или в Jupyter) нет встроенного механизма Task Retries, потому что процессы выполняются на одной машине в рамках одного приложения. Если сервер падает — запрос прерывается.

Однако, в экосистеме DataFusion есть механизмы отказоустойчивости, которые делятся на два уровня: локальный (Spilling) и распределенный (Apache Ballista / Ray).


1. Локальная отказоустойчивость (защита от OOM)

В Trino частой причиной падения задач является нехватка памяти (Out of Memory). В DataFusion реализован мощный механизм управления памятью.

Если DataFusion понимает, что оперативной памяти для агрегации или JOIN’а не хватает, он не “роняет” задачу, а начинает сбрасывать промежуточные данные на диск (Spill to Disk).

  • Это настраивается через конфигурацию `datafusion.execution.disk_manager`.
  • Это аналог локального `spill-enabled = true` в Trino. Запрос замедлится, но выполнится до конца, не упав с ошибкой.

2. Распределенная отказоустойчивость (Аналог Trino FTE)

Trino использует архитектуру Fault-Tolerant Execution (FTE), при которой промежуточные результаты (Shuffle Exchange) пишутся в S3, а упавшие воркеры заменяются, и их задачи (Tasks) перезапускаются координатором.

В мире DataFusion эту задачу решает не само ядро, а распределенные планировщики, построенные поверх него:

А. Apache Ballista (Официальный распределенный DataFusion)

Ballista — это надстройка над DataFusion, превращающая его в полноценный кластер (с Coordinator и Executors), архитектурно очень похожая на Apache Spark и Trino.

  • Task Retries: Если один из Executor’ов теряется из-за сбоя сети или железа, Ballista Coordinator замечает это и переназначает задачу (Task) другому воркеру.
  • Shuffle Spilling: Промежуточные данные между стадиями (Stages) записываются во временные файлы. Следовательно, если упала только последняя стадия, кластеру не нужно пересчитывать весь запрос с нуля — он прочитает промежуточные Shuffle-файлы и повторит только упавший кусок.
Б. DataFusion on Ray (datafusion-ray)

Сейчас огромную популярность набирает запуск DataFusion поверх кластера Ray.
Ray — это супер-устойчивый распределенный фреймворк. Интеграция `datafusion-ray` позволяет разбить SQL-запрос на граф задач прямо в Ray.

  • За отказоустойчивость, Retry-логику и восстановление упавших узлов (Actor/Task) здесь отвечает сам Ray, который делает это на уровне индустриального стандарта.
  • Это максимально близко к концепции отказоустойчивого кластера.

Резюме: Как получить “Trino-like” Fault Tolerance в DataFusion?

  1. Если вы используете локальный DataFusion (в Python или CLI): Отказоустойчивости уровня узлов нет, но есть защита от падений по памяти (Spill to Disk). Если упадет процесс — нужно перезапускать запрос руками.
  2. Если вам нужен настоящий Task Repeat / Fault Tolerance на сотнях серверов, где падение серверов — норма: вы используете движок DataFusion вместе с кластерным менеджером Apache Ballista или Ray, которые прозрачно обеспечат перезапуск задач (Retries) и сохранение промежуточных состояний (Shuffle), полностью повторяя логику Trino FTE.

UPD: В локальном тестировании есть некоторые особенности. Когда контейнеры внутри имеют свою сеть, то трино посылает в dbeaver ссылки. А есть хост не знает что это за минива или localstack-spooling, то оно отдаст кусок данных, а остальные части просто не доедут. Квери упадет как отмененная, так как клиент получил не все результаты. Короче, надо просто так сделать

sudo nano /etc/hosts

и вставить строку вашего s3 хоста.

127.0.0.1       localstack-spooling

то есть при спулинге клиент должен не только иметь сетевую связанность с s3 но различать dns имена корректно.

Короче сравния строк пройдено, все сошлося :)

со спулингом 2.2 сек
без спулинга 4.4 сек

Питончик 2.16 сек с чанками

в самом трино еще быстрее

все строки на месте: 150тыщъ

код !!


from trino.dbapi import connect
import json

Конфигурация –

TRINO_HOST = “localhost”
TRINO_PORT = 9999
TRINO_USER = “trino”
TRINO_CATALOG = “test_warehouse”
TRINO_SCHEMA = “test_schema”
OUTPUT_FILE = “output.json”
CHUNK_SIZE = 10000 # Количество строк, обрабатываемых за один раз

def export_to_json():
conn = connect(
host=TRINO_HOST,
port=TRINO_PORT,
user=TRINO_USER,
catalog=TRINO_CATALOG,
schema=TRINO_SCHEMA,
)
cursor = conn.cursor()

try:

Отключаем Fault-Tolerant Execution

cursor.execute(“SET SESSION retry_policy = ‘NONE’”)
cursor.execute(“SELECT * FROM my_table2”)

column_names = [desc[0] for desc in cursor.description]
row_count = 0

with open(OUTPUT_FILE, “w”, encoding=“utf-8”) as f:

Используем fetchmany для чанков

while True:
rows = cursor.fetchmany(CHUNK_SIZE)
if not rows:
break
for row in rows:
row_dict = dict(zip(column_names, row))
f.write(json.dumps(row_dict, ensure_ascii=False, default=str) + “\n”)
row_count += len(rows)
print(f“Processed {row_count} rows...”)

print(f“Successfully exported {row_count} rows to {OUTPUT_FILE}”)

finally:
cursor.close()
conn.close()

if __name__ == “__main__”:
export_to_json()

Вот еще с уточкой и чанками

код


import duckdb
import json

OUTPUT_FILE = “/home/jovyan/examples/output_duckdb.json”
CHUNK_SIZE = 10000

conn = duckdb.connect()

расширения и настройки (как у вас)

conn.execute(“INSTALL httpfs; LOAD httpfs;”)
conn.execute(“INSTALL iceberg; LOAD iceberg;”)
conn.execute(“SET memory_limit = ‘4GB’;”)
conn.execute(“SET s3_region = ‘us-east-1’;”)

conn.execute(“‘’
CREATE OR REPLACE SECRET minio_secret (
TYPE S3,
KEY_ID ‘minio-root-user’,
SECRET ‘minio-root-password’,
ENDPOINT ‘minio:9000’,
USE_SSL false,
URL_STYLE ‘path’
);
‘‘’)

conn.execute(‘‘’
CREATE OR REPLACE SECRET iceberg_secret (
TYPE ICEBERG,
TOKEN ‘dummy’
);
‘‘’)

conn.execute(‘‘’
ATTACH ‘test_warehouse’ AS lakekeeper_db (
TYPE ICEBERG,
ENDPOINT ’http://lakekeeper:8181/catalog/',
ACCESS_DELEGATION_MODE ‘none’,
SECRET iceberg_secret
);
‘‘’)

Используем cursor и fetchmany для чанков

cursor = conn.cursor()
cursor.execute(‘SELECT * FROM lakekeeper_db.test_schema.my_table2’)

Получаем имена колонок

col_names = [desc[0] for desc in cursor.description]

total_rows = 0
with open(OUTPUT_FILE, ‘w’, encoding=’utf-8’) as f:
while True:
rows = cursor.fetchmany(CHUNK_SIZE)
if not rows:
break
for row in rows:
row_dict = dict(zip(col_names, row))
f.write(json.dumps(row_dict, ensure_ascii=False, default=str) + ‘\n’)
total_rows += len(rows)
print(f’Обработано строк: {total_rows}’)

print(f’✅ Загружено и сохранено строк: {total_rows}”)
print(f“📁 Данные сохранены в {OUTPUT_FILE}”)
conn.close()

Можно даже так внутри уточки


import duckdb

OUTPUT_FILE = “/home/jovyan/examples/output_duckdb_direct.json”

conn = duckdb.connect()

Расширения и настройки

conn.execute(“INSTALL httpfs; LOAD httpfs;”)
conn.execute(“INSTALL iceberg; LOAD iceberg;”)
conn.execute(“SET memory_limit = ‘4GB’;”)
conn.execute(“SET s3_region = ‘us-east-1’;”)

Секрет для MinIO

conn.execute(“‘’
CREATE OR REPLACE SECRET minio_secret (
TYPE S3,
KEY_ID ‘minio-root-user’,
SECRET ‘minio-root-password’,
ENDPOINT ‘minio:9000’,
USE_SSL false,
URL_STYLE ‘path’
);
‘‘’)

Секрет для Iceberg REST

conn.execute(‘‘’
CREATE OR REPLACE SECRET iceberg_secret (
TYPE ICEBERG,
TOKEN ‘dummy’
);
‘‘’)

Подключение каталога Lakekeeper

conn.execute(‘‘’
ATTACH ‘test_warehouse’ AS lakekeeper_db (
TYPE ICEBERG,
ENDPOINT ’http://lakekeeper:8181/catalog/',
ACCESS_DELEGATION_MODE ‘none’,
SECRET iceberg_secret
);
‘‘’)

Экспорт в JSON (массив)

conn.execute(f’’’
COPY (
SELECT * FROM lakekeeper_db.test_schema.my_table2
) TO ‘{OUTPUT_FILE}’ (FORMAT JSON);
‘‘’)

print(f’✅ Данные сохранены в {OUTPUT_FILE}’)
conn.close()

К конце концов я использовал

localstack-spooling

protocol.spooling.enabled=true
# 256-битный ключ в формате base64. Вы можете сгенерировать свой с помощью команды `openssl rand -base64 32`
protocol.spooling.shared-secret-key=jxTKysfCBuMZtFqUf8UJDQ1w9ez8rynEJsJqgJf66u0=
catalog.management=dynamic

так

spooling-manager.name=filesystem
fs.s3.enabled=true
fs.location=s3://spooling-bucket/client-spooling/

s3.endpoint=http://localstack-spooling:4566
s3.region=us-east-1
s3.aws-access-key=test
s3.aws-secret-key=test
s3.path-style-access=true

и так

services:

  trino:
    build: ./trino
    environment:
      - CATALOG_MANAGEMENT=dynamic
      - LANCE_ALLOW_HTTP=true
      - AWS_ALLOW_HTTP=true
      - AWS_ACCESS_KEY_ID=minio-root-user
      - AWS_SECRET_ACCESS_KEY=minio-root-password
      - AWS_REGION=us-east-1
      - AWS_ENDPOINT_URL=http://minio:9000
      - CATALOG_MANAGEMENT=dynamic
      - JDK_JAVA_OPTIONS=--add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED
    healthcheck:
      test: ["CMD", "curl", "-I", "http://localhost:8080/v1/status"]
      interval: 2s
      timeout: 10s
      retries: 2
      start_period: 10s
    ports:
      - "9999:8080"
    volumes:
      - ./lance5.properties:/etc/trino/catalog/lance5.properties
      - ./lance_rest.properties:/etc/trino/catalog/lance_rest.properties
      - ./lance_ice.properties:/etc/trino/catalog/lance_ice.properties
      # --- ДОБАВЬТЕ ЭТУ СТРОКУ ---
      - ./spooling-manager.properties:/etc/trino/spooling-manager.properties
      # (При необходимости пробросьте и config.properties, если он не копируется при build: ./trino)
      - ./config.properties:/etc/trino/config.properties
      - spooling-data:/tmp/spooling
    networks:
      - lakekeeper-network
    depends_on:
      localstack-setup:    # <--- Trino ждет, пока AWS CLI не создаст бакет!
        condition: service_completed_successfully

  localstack-spooling:
    image: localstack/localstack:3.4.0    # Жестко фиксируем бесплатную рабочую версию!
    container_name: localstack-spooling
    ports:
      - "4566:4566"
    environment:
      - SERVICES=s3
      - AWS_DEFAULT_REGION=us-east-1
    networks:
      - lakekeeper-network

  localstack-setup:
    image: amazon/aws-cli:latest
    container_name: localstack-setup
    depends_on:
      - localstack-spooling
    restart: "no"
    environment:
      - AWS_ACCESS_KEY_ID=test
      - AWS_SECRET_ACCESS_KEY=test
      - AWS_DEFAULT_REGION=us-east-1
    entrypoint: >
      /bin/sh -c "
        echo 'Waiting for LocalStack to fully start...';
        sleep 10;
        aws --endpoint-url=http://localstack-spooling:4566 s3 mb s3://spooling-bucket;
        echo 'LocalStack bucket created successfully!';
      "
    networks:
      - lakekeeper-network
      
  jupyter:
    image: quay.io/jupyter/pyspark-notebook:2024-10-14
    depends_on:
      lakekeeper:
        condition: service_healthy
      # Исправлено: теперь зависим от рабочего setup сервиса
      lakekeeper-setup:
        condition: service_completed_successfully
      trino:
        condition: service_healthy
      # Удалено: starrocks (сервис не описан в compose файле)
    command: start-notebook.sh --NotebookApp.token=''
    volumes:
      - ./notebooks:/home/jovyan/examples/
      - spooling-data:/tmp/spooling
    networks:
      - lakekeeper-network
    ports:
      - "8888:8888"

  # Сервис initialwarehouse УДАЛЕН, так как он дублировал lakekeeper-setup 
  # и ссылался на несуществующие сервисы (bootstrap, createbuckets).

  postgres-lakekeeper:
    image: postgres:17
    container_name: postgres-lakekeeper
    environment:
      POSTGRES_USER: lakekeeper
      POSTGRES_PASSWORD: lakekeeper
      POSTGRES_DB: lakekeeper
    ports:
      - "5435:5432"
    volumes:
      - lakekeeper-postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U lakekeeper -d lakekeeper"]
      interval: 2s
      timeout: 10s
      retries: 5
    networks:
      - lakekeeper-network

  minio:
    image: minio/minio:latest
    container_name: minio-lakekeeper
    environment:
      MINIO_ROOT_USER: minio-root-user
      MINIO_ROOT_PASSWORD: minio-root-password
      # MINIO_DOMAIN: minio
    command: server /data --console-address ":9001"
    ports:
      - "19000:9000"
      - "19001:9001"
    volumes:
      - lakekeeper-minio-data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 2s
      timeout: 10s
      retries: 5
    networks:
      - lakekeeper-network

  minio-setup:
    image: minio/mc:latest
    container_name: minio-setup
    depends_on:
      minio:
        condition: service_healthy
    entrypoint: >
      /bin/sh -c "
        mc alias set myminio http://minio:9000 minio-root-user minio-root-password &&
        mc mb myminio/warehouse --ignore-existing &&
        echo 'MinIO bucket created'
      "
    networks:
      - lakekeeper-network

  lakekeeper-migrate:
    image: quay.io/lakekeeper/catalog:latest-main
    container_name: lakekeeper-migrate
    depends_on:
      postgres-lakekeeper:
        condition: service_healthy
    environment:
      - LAKEKEEPER__PG_ENCRYPTION_KEY=test-encryption-key-not-secure
      - LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://lakekeeper:lakekeeper@postgres-lakekeeper:5432/lakekeeper
      - LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://lakekeeper:lakekeeper@postgres-lakekeeper:5432/lakekeeper
    restart: "no"
    command: ["migrate"]
    networks:
      - lakekeeper-network

  lakekeeper:
    image: quay.io/lakekeeper/catalog:latest-main
    container_name: lakekeeper
    depends_on:
      lakekeeper-migrate:
        condition: service_completed_successfully
      minio-setup:
        condition: service_completed_successfully
    environment:
      - LAKEKEEPER__PG_ENCRYPTION_KEY=test-encryption-key-not-secure
      - LAKEKEEPER__PG_DATABASE_URL_READ=postgresql://lakekeeper:lakekeeper@postgres-lakekeeper:5432/lakekeeper
      - LAKEKEEPER__PG_DATABASE_URL_WRITE=postgresql://lakekeeper:lakekeeper@postgres-lakekeeper:5432/lakekeeper
      - LAKEKEEPER__AUTHZ_BACKEND=allowall
      - RUST_LOG=info
    command: ["serve"]
    healthcheck:
      test: ["CMD", "/home/nonroot/lakekeeper", "healthcheck"]
      interval: 2s
      timeout: 10s
      retries: 5
      start_period: 5s
    ports:
      - "8282:8181"
    networks:
      - lakekeeper-network

  lakekeeper-bootstrap:
    image: curlimages/curl
    container_name: lakekeeper-bootstrap
    depends_on:
      lakekeeper:
        condition: service_healthy
    restart: "no"
    command:
      - -w
      - "%{http_code}"
      - "-X"
      - "POST"
      - "-v"
      - "http://lakekeeper:8181/management/v1/bootstrap"
      - "-H"
      - "Content-Type: application/json"
      - "--data"
      - '{"accept-terms-of-use": true}'
      - "-o"
      - "/dev/null"
    networks:
      - lakekeeper-network

  lakekeeper-setup:
    image: curlimages/curl
    container_name: lakekeeper-setup
    depends_on:
      lakekeeper-bootstrap:
        condition: service_completed_successfully
    restart: "no"
    entrypoint: ["/bin/sh", "-c"]
    command:
      - |
        echo "Creating test_warehouse..."
        curl -sf -X POST "http://lakekeeper:8181/management/v1/warehouse" \
          -H "Content-Type: application/json" \
          -d '{
            "warehouse-name": "test_warehouse",
            "project-id": "00000000-0000-0000-0000-000000000000",
            "storage-profile": {
              "type": "s3",
              "bucket": "warehouse",
              "endpoint": "http://minio:9000",
              "region": "us-east-1",
              "path-style-access": true,
              "flavor": "minio",
              "sts-enabled": false
            },
            "storage-credential": {
              "type": "s3",
              "credential-type": "access-key",
              "aws-access-key-id": "minio-root-user",
              "aws-secret-access-key": "minio-root-password"
            }
          }' && echo "Warehouse created successfully" || echo "Failed to create warehouse"
    networks:
      - lakekeeper-network

volumes:
  lakekeeper-postgres-data:
  lakekeeper-minio-data:
  spooling-data:
  
networks:
  lakekeeper-network:
    driver: bridge

49 Мегабайт Боли: Экономика враждебного веб-дизайна

Ссылка на оригинальную публикацию есть тут The 49MB Web Page.

Опубликовано: 12 апреля 2026 г. | Оригинал: 12 марта 2026 г.

МненИИе  🤖  

Если бы отвлечение внимания пользователей было олимпийским видом спорта, новостные издания забирали бы все золотые медали. Зайдя на сайт крупного новостного портала вроде New York Times, чтобы просто прочитать пару заголовков, вы столкнетесь с лавиной: 422 сетевых запроса и 49MB загруженных данных. После того как страница наконец-то «успокоится» спустя пару минут, отпадает любой вопрос о том, почему каждый уважающий себя IT-специалист устанавливает блокировщики рекламы на все устройства своих близких.

Чтобы осознать масштаб феномена «49-мегабайтной веб-страницы», давайте вернемся в прошлое. Размер этой страницы превышает объем операционной системы Windows 95 (которая помещалась на 28 дискетах!). В эпоху расцвета iPod стандартный MP3-трек высокого качества (битрейт 192 kbps) занимал около 4-5MB. Таким образом, одна современная статья весит как полноценный музыкальный альбом из 10–12 песен.

Время загрузки в 2006 году ≈ 1.5 Mbps 49 MB×8 бит ≈ 261 секунда

Спустя 20 лет аппаратное обеспечение шагнуло далеко вперед, но современные рекламные технологии (ad-tech) полностью нивелировали этот прогресс своей плохой архитектурой и бесконечным раздуванием кода.

Почему так происходит? Экономика Hostile Architecture

Издатели не злодеи, они просто в отчаянии. Попав в «смертельную спираль» programmatic-рекламы, они жертвуют долгосрочной лояльностью читателей ради сиюминутных копеек с показов (CPM). Современная рекламная индустрия разделила создателя контента и рекламодателя.

Каждое враждебное UX-решение проистекает из одной формулы: чем дольше вы заперты на странице взаимодействия, тем выше доход. Ваше разочарование — это их продукт. Мы можем описать общую стоимость взаимодействия (Interaction Cost) как математическую сумму:

C total =∑ ( C mental + C physical)

Вместо комфортного чтения пользователи сталкиваются с системой, которая максимизирует $C_{total}$, чтобы выжать максимум метрик из человеческого когнитивного ресурса.

Технические детали враждебного дизайна (CLS, Z-Index, Трекинг)

  • Z-Index Warfare (Предварительная засада): При загрузке страницы вас встречает баннер файлов cookie (занимает 30% экрана), затем всплывающее окно «Подпишитесь на рассылку», и одновременно браузер спамит запрос на отправку уведомлений. Доступ к 5 KB текста статьи превращается в полосу препятствий.
  • CLS-катастрофа (Cumulative Layout Shift): Вы начали читать, как вдруг текст прыгает на 250 пикселей вниз. Почему? Рекламная сеть завершила фоновые торги и встроила `iframe` над видимой областью. Это вызывает дезориентацию и напрямую ведет к высокому проценту отказов (bounce rate).
  • Невидимые аукционы и перегрузка Mobile CPU: Пока вы читаете абзац, браузер вынужден обрабатывать десятки параллельных ставок от `fastlane.json` или систем Amazon. Разбор мегабайтов `JS` монополизирует основной поток браузера.
  • Прилипающие видео и закон Фиттса: При прокрутке видео открепляется и закрепляется в углу экрана. Кнопка закрытия «X» делается микроскопической, что нарушает Закон Фиттса, согласно которому время достижения цели зависит от расстояния до нее и ее размера:
    T = a + blog 2 ( 1 + WD)
  • Налог на «Толстый палец» (Fat-finger tax): Расположение кнопок закрытия вплотную к кликабельной зоне рекламы — это математически просчитанный риск рекламных команд для генерации случайных кликов. Это не баг, это фича.

Альтернативные решения для разработчиков

Если маркетинговая команда настаивает на автовоспроизведении видео, разработчики обязаны использовать `IntersectionObserver`. Это позволит уважать ресурсы пользователя (батарею и CPU) при прокрутке страницы:

// Пример базовой реализации для паузы видео вне зоны видимости
const videoElement = document.querySelector('video.ads-player');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      videoElement.play();
    } else {
      videoElement.pause(); // Уважаем выбор пользователя!
    }
  });
});

observer.observe(videoElement);

Также шапки сайтов следует скрывать при событии `scrollDown` и показывать только при `scrollUp`, освобождая драгоценное вертикальное пространство на мобильных устройствах.


Критические комментарии к проблеме

Оригинальная статья поднимает важную проблему UI/UX, однако дискуссию стоит разбавить долей конструктивной критики:

  1. Однобокий взгляд на монетизацию: Журналистика стоит денег. Расследования, сервера, зарплаты редакторов — всё это требует финансирования. Падение доходов от печатной прессы заставило издания полагаться на рекламные сети. Хотя 49 MB — это абсурд, сама по себе агрессивная реклама является следствием того, что пользователи массово отказываются платить за подписки (Paywalls).
  2. Эффект домино от Ad-blockers: Существует парадокс: чем больше продвинутых интернет-пользователей устанавливают блокировщики, тем меньше инвентаря остается у издателя. Чтобы компенсировать потери, издания вынуждены внедрять ещё более агрессивные скрипты и “липкие” видео для оставшейся, менее технически грамотной аудитории.
  3. Асинхронность и реальный пользовательский опыт: Измерять “зло” веб-страницы исключительно её «боевым весом» (49MB) некорректно. Большинство современных трекеров браузеры загружают асинхронно или отложенно (с атрибутом `defer`). Трудность вызывает не сам объем загружаемых байтов, а именно блокировка главного потока браузера и смещение макета (CLS).

Итог

Современный новостной веб-дизайн оказался в заложниках у метрик. Системы, созданные для вовлечения, трансформировались в «цифровую враждебную архитектуру», доводящую пользователя до ментального истощения. Страницы, превышающие по объему старые операционные системы, использование «тёмных паттернов» (модальные окна, микроскопические крестики закрытия) и беспощадная нагрузка на процессор телефона убивают самое главное — доверие между читателем и изданием.

Создателям контента следует помнить: если пользователь тратит свой когнитивный бюджет на то, чтобы закрыть 4 баннера до прочтения первого слова, никакая «оптимизация конверсии» не заставит его оформить платную подписку. Лучший веб-дизайн — это тот, который уважает время и внимание читателя.

Ventoy: Мультизагрузочная флешка нового поколения

Ventoy — это бесплатная утилита с открытым исходным кодом, которая навсегда изменит ваш подход к созданию загрузочных USB-накопителей. Вместо того чтобы каждый раз форматировать флешку для записи нового образа Windows или Linux, Ventoy позволяет просто копировать файлы образов на накопитель, как на обычную флешку.


Зачем это нужно?

Традиционные инструменты (например, Rufus или UltraISO) извлекают содержимое ISO-образа и записывают его на флешку, форматируя её. Если вам нужна другая операционная система, весь процесс приходится повторять.

Преимущества Ventoy:

  • Экономия времени: Не нужно форматировать флешку снова и снова. Вы делаете это лишь один раз при установке самого Ventoy.
  • Мультизагрузочность: Вы можете закинуть на одну флешку десятки образов (Windows, Ubuntu, различные антивирусные LiveCD, инструменты для восстановления). При загрузке Ventoy покажет удобное меню со списком всех найденных образов.
  • Поддержка форматов: Работает не только с ISO, но и с WIM, IMG, VHD(x) и EFI файлами.
  • Сохранение обычных данных: Оставшееся свободное место на флешке можно использовать для хранения обычных файлов (документов, фотографий, портативных программ).

Как использовать

Процесс использования максимально прост и состоит из нескольких шагов:

  1. Скачивание и установка: Скачайте программу с официального сайта и запустите. Выберите вашу флешку в списке и нажмите кнопку `Install` (Установить). Внимание: все данные на флешке будут удалены!
  2. Копирование образов: После установки флешка разделится на скрытый загрузочный раздел и видимый раздел для данных. Просто скопируйте нужные вам ISO-файлы (или другие поддерживаемые форматы) в видимый раздел через проводник.
  3. Загрузка: Вставьте флешку в компьютер, в BIOS/UEFI выберите загрузку с USB. Появится меню Ventoy, где вы с помощью стрелочек на клавиатуре сможете выбрать нужный образ и запустить его.

Какие есть ограничения и особенности?

Несмотря на всю свою гениальность, у Ventoy есть несколько нюансов, о которых стоит знать:

список ограничений

  • Secure Boot (Безопасная загрузка): Хотя Ventoy поддерживает Secure Boot, на некоторых компьютерах при первой загрузке может потребоваться ручное добавление ключа сертификата (enroll key). Процесс описан на официальном сайте, но для новичков это может стать небольшим препятствием. Для обхода проблемы Secure Boot в BIOS можно временно отключить.
  • Специфичные ОС: Хотя Ventoy тестировался на более чем 1000 различных ISO-образов и поддерживает 99% популярных дистрибутивов, некоторые экзотические или очень старые системы могут не загрузиться корректно.
  • Фрагментация файлов: Если вы часто записываете и удаляете образы, они могут фрагментироваться. Ventoy не поддерживает загрузку сильно фрагментированных ISO-файлов на файловой системе exFAT. В таких случаях может потребоваться дефрагментация флешки.
  • Зависимость от BIOS/UEFI: Успешная загрузка иногда зависит от конкретной реализации прошивки материнской платы. Некоторые старые устройства с кривым BIOS могут не распознать загрузчик.

Итог

Ventoy — это инструмент категории “must-have” для системных администраторов, энтузиастов и всех, кому приходится периодически переустанавливать операционные системы или пользоваться загрузочными инструментами. Один раз подготовив такую флешку, вы забудете о рутине с форматированием навсегда.

StarRocks: Архитектура, Практика и место в современном Data Stack

StarRocks — это аналитическая MPP-база данных нового поколения.
Если коротко, она пытается решить трилемму аналитики: объединить скорость ClickHouse (за счет векторизации и C++), гибкость Trino (поддержка сложных JOIN-ов) и простоту использования MySQL (совместимый протокол).

Это короткое руководство проведет вас от понимания архитектуры до построения простого конвейера загрузки данных (ETL) в домашнем продакшене.


Часть 1. Архитектура: FE и BE

В отличие от PostgreSQL (монолит) или ClickHouse (где узлы часто одноранговые), StarRocks имеет четкое разделение ролей. Это критически важно для понимания масштабирования и эксплуатации.

1. FE (Frontend) — “Мозг”

Написан на Java.

  • Роль: Управляющий слой.
  • Функции:
    • Принимает подключения клиентов (по протоколу MySQL).
    • Хранит метаданные (схемы таблиц, права доступа).
    • Парсит SQL и строит план выполнения запроса (Query Plan).
    • Управляет транзакциями загрузки данных.
  • Масштабирование: Обычно запускают 1 или 3 узла для обеспечения высокой доступности (HA).
  • Важно: Клиенты (DBeaver, BI, сurl) подключаются только к FE.

2. BE (Backend) — “Мускулы”

Написан на C++ (использует SIMD-инструкции процессора).

  • Роль: Слой хранения и вычислений.
  • Функции:
    • Физически хранит данные (в колоночном формате).
    • Выполняет “тяжелую” работу: фильтрацию, агрегацию, JOIN-ы.
    • Управляет репликацией данных.
  • Масштабирование: Можно добавлять узлы линейно. Чем больше BE, тем быстрее выполняются запросы и тем больше данных можно хранить.

В Docker All-in-One: Оба компонента упакованы в один контейнер для удобства, но слушают разные порты:

  • `9030`: FE (SQL интерфейс, сюда идет DBeaver).
  • `8030`: FE (HTTP API для загрузки Stream Load, сюда идет curl).
  • `8040`: BE (HTTP API метрик и логов).

Часть 2. Быстрый старт (Docker Compose)

Мы поднимем стек StarRocks и MinIO (S3-совместимое хранилище), используя bridge-сеть для связности.

Файл `docker-compose.yml` (Полностью рабочий пример):

version: "3.9"

networks:
  starrocks-stack-network:
    driver: bridge

services:
  starrocks:
    image: starrocks/allin1-ubuntu:4.0-latest
    container_name: starrocks
    hostname: starrocks.local.com
    platform: "linux/amd64"
    restart: unless-stopped
    ports:
      - "9030:9030" # MySQL Protocol (SQL клиенты)
      - "8030:8030" # FE HTTP (Stream Load)
      - "8040:8040" # BE HTTP (Logs/Metrics)
    environment:
      - TZ=UTC
    networks:
      starrocks-stack-network:
    volumes:
      # Персистентность данных (чтобы данные не исчезли после рестарта)
      - ${HOME}/dv/starrocks/be/storage:/data/deploy/starrocks/be/storage
      - ${HOME}/dv/starrocks/be/log:/data/deploy/starrocks/be/log
      - ${HOME}/dv/starrocks/fe/meta:/data/deploy/starrocks/fe/meta
      - ${HOME}/dv/starrocks/fe/log:/data/deploy/starrocks/fe/log

  minio:
    image: quay.io/minio/minio
    container_name: minio
    platform: "linux/amd64"
    hostname: minio.local.com
    restart: unless-stopped
    ports:
      - "9000:9000" # S3 API
      - "9001:9001" # Web UI
    networks:
      starrocks-stack-network:
    environment:
      MINIO_ROOT_USER: root
      MINIO_ROOT_PASSWORD: rootroot
    volumes:
      - ${HOME}/dv/minio/data:/data
    command: server /data --console-address ":9001"

Запуск:
`docker-compose up -d`


Часть 3. Моделирование данных (Table Design)

В StarRocks нельзя просто “создать таблицу”. Нужно выбрать тип ключа (Key Model), который определит, как база будет хранить и обновлять данные.

Подключение (DBeaver): `localhost:9030`, User: `root`, Password: (пусто).

CREATE DATABASE IF NOT EXISTS demo_db;
USE demo_db;

1. Primary Key Model (Для изменяемых данных)

Это “флагманская” возможность StarRocks. Она поддерживает быстрые Upsert (вставка новых или обновление старых записей по ID) в реальном времени.

CREATE TABLE IF NOT EXISTS users (
    user_id INT NOT NULL,
    username VARCHAR(50),
    email VARCHAR(100),
    register_date DATE, 
    city VARCHAR(50)
)
PRIMARY KEY (user_id) -- Уникальный ключ
DISTRIBUTED BY HASH(user_id) -- Распределение данных
PROPERTIES (
    "replication_num" = "1" -- Для локального теста ставим 1 реплику
);

2. Aggregate Key Model (Для витрин данных)

База автоматически агрегирует данные при вставке. Если вы вставите новую продажу с *существующими* датой и категорией, StarRocks не создаст новую строку, а прибавит суммы к уже существующей строке. Это экономит место и ускоряет `GROUP BY`.

CREATE TABLE IF NOT EXISTS daily_sales (
    report_date DATE NOT NULL,
    category VARCHAR(50) NOT NULL,
    
    -- Метрики с функцией агрегации:
    total_amount BIGINT SUM DEFAULT "0", 
    items_sold INT SUM DEFAULT "0"       
)
AGGREGATE KEY (report_date, category)
DISTRIBUTED BY HASH(report_date) BUCKETS 3
PROPERTIES (
    "replication_num" = "1"
);

Часть 4. загрузка данных users (Stream Load)

Для загрузки данных в продакшене мы используем Service Account (Техническую учетную запись). Это стандарт безопасности: мы не используем `root` и не используем токены в конфигах (так как они требуют перезагрузки кластера для смены).

Шаг 1. Создание сервисного пользователя (SQL)

Выполнять под `root`:

-- 1. Создаем пользователя-бота
CREATE USER IF NOT EXISTS 'etl_loader'@'%' IDENTIFIED BY 'SecretPass123!';

-- 2. Даем права ТОЛЬКО на вставку и чтение в базе demo_db
GRANT INSERT, SELECT ON demo_db.* TO 'etl_loader'@'%';

-- Права применяются мгновенно.

Шаг 2. Загрузка сложного JSON через CURL

Stream Load — это самый быстрый способ загрузки (до 100 МБ/сек на узел). Он поддерживает транзакционность (ACID).

Пример файла `users.json`:

{
  "users": [
    {"user_id": 101, "username": "alex", "email": "a@test.com", "city": "NY"},
    {"user_id": 102, "username": "bob", "email": "b@test.com", "city": "LA"}
  ]
}

Команда загрузки (Terminal):

curl --location-trusted \
    -u etl_loader:SecretPass123! \
    -H "Expect: 100-continue" \
    -H "format: json" \
    -H "strip_outer_array: true" \
    -H "json_root: $.users" \
    -H "jsonpaths: [\"$.user_id\", \"$.username\", \"$.email\", \"$.city\"]" \
    -H "columns: user_id, username, email, city" \
    -T "users.json" \
    -XPUT http://localhost:8030/api/demo_db/users/_stream_load

Ответ

{
    "TxnId": 9596,
    "Label": "a9a37ab6-3678-4c08-95b7-2fd8b6ae973e",
    "Db": "demo_db",
    "Table": "users",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 2,
    "NumberLoadedRows": 2,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 177,
    "LoadTimeMs": 153,
    "BeginTxnTimeMs": 2,
    "StreamLoadPlanTimeMs": 2,
    "ReadDataTimeMs": 0,
    "WriteDataTimeMs": 26,
    "CommitAndPublishTimeMs": 121
}%

Шаг 3. Загрузка в Aggregate Table (Example)

Давайте “дольем” данные в таблицу продаж. Агрегация произойдет на лету.
Файл sales.json (простой список):

[
    {"dt": "2023-11-01", "cat": "Electronics", "amt": 100, "qty": 1},
    {"dt": "2023-11-01", "cat": "Electronics", "amt": 50,  "qty": 1}
]

curl --location-trusted \
    -u etl_loader:SecretPass123! \
    -H "format: json" \
    -H "Expect: 100-continue" \
    -H "strip_outer_array: true" \
    -H "jsonpaths: [\"$.dt\", \"$.cat\", \"$.amt\", \"$.qty\"]" \
    -H "columns: report_date, category, total_amount, items_sold" \
    -T "sales.json" \
    -XPUT http://localhost:8030/api/demo_db/daily_sales/_stream_load

Ответ:

{
    "TxnId": 9613,
    "Label": "bce0721a-dc2d-4927-be93-e0979a57873d",
    "Db": "demo_db",
    "Table": "daily_sales",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 2,
    "NumberLoadedRows": 2,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 143,
    "LoadTimeMs": 52,
    "BeginTxnTimeMs": 3,
    "StreamLoadPlanTimeMs": 2,
    "ReadDataTimeMs": 0,
    "WriteDataTimeMs": 24,
    "CommitAndPublishTimeMs": 20
}%

Разбор заголовков:

  • `-u ...`: Авторизация сервисным пользователем.
  • `Expect: 100-continue`: Критически важно для надежности передачи больших файлов.
  • `json_root: $.users`: Указывает базе, что данные лежат внутри ключа `users`.
  • `strip_outer_array: true`: Говорит базе, что внутри лежит массив `[...]` и его нужно “развернуть” в отдельные строки.

Часть 5. Совместимость и Trino Dialect

Одна из сильных сторон StarRocks — способность “притворяться” другими базами данных для облегчения миграции.

Если у вас есть дашборды, написанные на диалекте Trino (Presto), вам не нужно переписывать все SQL-запросы.

Пример трансляции функций:

-- Функция Trino, которой нет в StarRocks
SELECT doy(date '2022-03-06'); 
-- Ошибка: No matching function...

-- Проверяем, как StarRocks переведет этот запрос
TRANSLATE TRINO select doy(date '2022-03-06');
-- Результат: SELECT dayofyear('2022-03-06')

-- Включаем режим автоматической трансляции в сессии
SET sql_dialect = 'trino'; 

-- Теперь запрос выполняется корректно, но это не правда. а вот так SELECT dayofyear('2022-03-06') работает. Может бага или у меня версия не та. 
SELECT doy(date '2022-03-06');   

-- Возвращаем нативный режим
SET sql_dialect = 'starrocks';

*(Примечание: Поддержка диалекта постоянно расширяется, но некоторые специфические функции могут требовать ручной замены).*


Итог: Сравнение и Выбор решения ( грубо )

Характеристика StarRocks ClickHouse Trino (Presto)
Основной сценарий OLAP-витрины с JOIN-ами и обновлениями данных Сбор логов, событий, метрик (Append-only) Федерация данных (запрос к S3 + Postgres + Kafka одновременно)
JOIN производительность ⭐⭐⭐ (Excellent, CBO оптимизатор) ⭐ (Слабо, требует денормализации) ⭐⭐⭐ (Excellent)
Обновление (UPDATE) ⭐⭐⭐ (Работает как в OLTP, Primary Key) ⭐ (Тяжелые асинхронные ALTER) ❌ (Обычно только полная перезапись партиций), iceberg не в счёт :)
Язык Engine C++ (SIMD Vectorized) C++ (SIMD Vectorized) Java (JVM)
Место в стеке Serving Layer (Быстрый доступ для BI) Storage Layer (Хранение логов) Query Engine (Ad-hoc запросы к Data Lake)

Выбирайте StarRocks, если:

  1. Вам нужна “витрина” для BI (Superset/Tableau), где данные должны быть всегда свежими (Real-time updates).
  2. Ваш бизнес требует сложных аналитических запросов с множеством JOIN-ов, и ClickHouse не справляется/падает по памяти.
  3. Вы хотите использовать стандартный протокол MySQL без установки проприетарных драйверов.

Наследие Юргена Хабермаса: Философ коммуникации и защитник модерна

Юрген Хабермас (18 июня 1929 — 14 марта 2026) — немецкий философ и социолог, крупнейший представитель второго поколения Франкфуртской школы, чье творчество оказало глубокое влияние на политическую философию, теорию права, этику и социальную теорию второй половины XX — начала XXI века . Его часто называли «самым главным философом Германии», наследником традиций Иммануила Канта и Карла Маркса . Он ушел из жизни 14 марта 2026 года в возрасте 96 лет.

Основные идеи и определения

Философский проект Хабермаса огромен, но в его основе лежит стремление защитить проект эпохи Просвещения (модерна) и переосмыслить природу разума в категориях не субъекта, а интерсубъективности и коммуникации.

1. Коммуникативная рациональность и теория коммуникативного действия
Это краеугольный камень его учения. Хабермас противопоставил инструментальному действию (ориентированному на успех и эффективность, характерному для сферы труда и бюрократии) действие коммуникативное. Коммуникативное действие — это взаимодействие индивидов, направленное на достижение взаимопонимания и консенсуса . В отличие от классической философии, идущей от отношения «субъект-объект», Хабермас предложил парадигму «субъект-субъект», где язык и дискурс становятся основой для выработки общих норм и ценностей .

2. Этика дискурса
Развитая совместно с Карлом-Отто Апелем, эта концепция предлагает новый взгляд на мораль. Место кантовского категорического императива, монологического по своей природе, занимает принцип дискурса: значимыми могут считаться только те нормы, с которыми согласились бы все участники дискуссии в условиях свободного от принуждения обсуждения .

3. Публичная сфера (Öffentlichkeit)
В своей ранней работе «Структурная трансформация публичной сферы» (1962) Хабермас описал, как в Новое время возникло пространство (салоны, кофейни, пресса), где частные лица могли собираться и обсуждать вопросы, представляющие общий интерес, формируя общественное мнение, способное контролировать власть . В конце жизни он вернулся к этой теме, анализируя кризис публичной сферы в эпоху цифровых платформ и социальных сетей .

4. Проект модерна и полемика с постмодернистами
Хабермас, в отличие от Жана-Франсуа Лиотара и других постмодернистов, отказывался считать проект модерна завершенным. Он видел в модерне «незавершенный проект», основанный на вере в силу разума. По его мнению, проблемы современности связаны не с провалом разума как такового, а с его искажением — доминированием одной лишь инструментальной рациональности, которая «колонизирует» «жизненный мир» (мир повседневного общения, семьи, культуры) .

5. Делиберативная демократия
Хабермас развил теорию демократии, в которой центр тяжести смещается с процедуры голосования на процесс открытого обсуждения (делиберации). Легитимность политических решений проистекает не просто из воли большинства, а из качества предшествующей дискуссии, в которой участвуют свободные и равные граждане .

6. Постсекулярное общество
В поздний период творчества Хабермас активно исследовал роль религии в современном мире, вводя понятие «постсекулярного общества». Это общество, в котором религия не исчезает, а продолжает существовать наряду с наукой и требует к себе толерантного отношения, при этом религиозные высказывания должны быть «переведены» на общедоступный язык для участия в общемировоззренческом дискурсе.

Что ему удалось?

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

Его главная удача — построение мощной альтернативы как пессимизму ранней Франкфуртской школы (Адорно, Хоркхаймер), так и релятивизму постмодернистов. Он предложил позитивную программу: вместо тотальной критики разума — его «перезагрузку» на коммуникативных основах .

Ему удалось ввести в академический и политический оборот понятия, ставшие общеупотребительными («коммуникативное действие», «публичная сфера», «делиберативная демократия»). Его идеи стали теоретической основой для развития гражданского общества и дискуссий о будущем Европейского Союза .

Он выиграл ключевые интеллектуальные споры своего времени, последовательно защищая универсалистские ценности Просвещения, свободу и демократию.

Что ему не удалось?

Главный упрек в адрес Хабермаса — чрезмерная идеализация «ненарушенной коммуникации». Критики, и с годами он сам это признавал, указывают на то, что его концепция «идеальной речевой ситуации» (свободного от власти и принуждения дискурса) является труднодостижимым идеалом в реальном мире, пронизанном отношениями господства и неравенством доступа к дискурсу .

Сложность и абстрактность его языка («непроходимый» стиль) делают его работы трудными для чтения не только для широкой публики, но порой и для специалистов.

В конце жизни, как отмечают некоторые критики, его анализ кризиса публичной сферы в эпоху интернета оказался недостаточно глубоким. Обеспокоенный «интернет-партизанами» и платформами, подрывающими, по его мнению, рациональный консенсус, он, возможно, недооценил глубину политического и социального кризиса западных обществ, списав его на сбои в работе медиа, а не на системные проблемы .

Итог и самый большой вклад

Юрген Хабермас на протяжении более чем шести десятилетий оставался «совестью» немецкой и европейской интеллигенции, неизменно выступая с позиций разума и эмансипации. Он оставил после себя не просто собрание сочинений, а целую школу мысли и набор инструментов для анализа общества.

Самым большим его вкладом в мировую философию по праву считается теория коммуникативного действия. Эта работа не только изменила оптику социальной теории, сместив фокус с субъекта на диалог, но и подарила надежду на то, что общество может быть устроено не только на основе рынка (денег) и административной власти, но и на основе солидарности и аргументированного консенсуса. Эта идея остается его главным интеллектуальным завещанием человечеству.

Действительно ли данные готовы к ИИ

Автор: Джейкоб Мэтсон

https://motherduck.com/blog/bird-bench-and-data-models

Несколько месяцев назад я писал о том, почему нам может не понадобиться семантический слой. Аргумент заключался в том, что ИИ может обнаруживать бизнес-логику из истории запросов, вместо того чтобы заставлять людей заранее определять каждую метрику. Я верил в это. Но у меня не было данных, чтобы это доказать.

Теперь они у меня есть.

Все началось с вопроса одного из наших инвесторов: *“Как различные модели справляются с BIRD при использовании MotherDuck MCP?”* Поэтому я провел эксперимент. Три передовые LLM модели (`Claude Opus 4.5`, `GPT-5.2` и `Gemini 3 Flash`), каждая из которых подключена к базе данных через сервер `MotherDuck MCP`, были запущены на наборе данных `BIRD Mini-Dev`.

Пояснение:

  • MCP (Model Context Protocol):** Стандарт, позволяющий ИИ-моделям безопасно и стандартизировано подключаться к внешним источникам данных и инструментам.
  • BIRD (BIg Bench for Large-scale Database Grounded Text-to-SQL):** Популярный и сложный бенчмарк (набор тестов) для оценки того, насколько хорошо нейросети умеют переводить естественный язык в SQL-запросы.
  • Mini-Dev:** Это официальная выборка из 500 вопросов для разработки из бенчмарка BIRD. Она охватывает 11 баз данных в сферах финансов, спорта, образования и здравоохранения.

Модели данных здесь простые. В среднем 7 таблиц на базу данных. Ни в одной нет больше 13 таблиц. Объединения (joins) в основном «один-ко-многим», максимальная глубина — два или три перехода, ноль отношений «многие-ко-многим». Это тот тип схемы, который можно понять за пять минут, прочитав `DDL`.

Пояснение: `DDL` (Data Definition Language) — это часть SQL, используемая для описания структуры базы данных (создание таблиц, колонок, связей).

Результат? 95% точности. Никакого семантического слоя. Никакой истории запросов. Никакого специального контекста. Только схема базы данных.

Но это число требует «звездочки» (примечания), и, честно говоря, эта звездочка — самая интересная часть.

Что на самом деле означают 95%

Вот что я измерял на самом деле.

Бенчмарк BIRD оценивает точность, используя Execution Accuracy (EX): запускается предсказанный SQL и «золотой» (эталонный) SQL, сравниваются наборы результатов, и ставится бинарная оценка «сдал/не сдал». При этих строгих правилах текущий уровень развития технологий (SOTA) составляет около 76. Мои модели набрали 64 на тренировочной выборке и 58 на тестовой.

Звучит плохо. Но у строгой оценки BIRD есть хорошо задокументированная проблема. В статье 2025 года, представляющей метрику `FLEX`, было обнаружено, что точность выполнения (execution accuracy) BIRD совпадает с оценками экспертов-людей только в 62% случаев. Почти 4 из 10 суждений ошибочны, в основном это ложноотрицательные результаты, когда бенчмарк отвергает ответы, которые люди бы приняли.

Эти 62 бросились мне в глаза, потому что они почти точно совпадают с моей смешанной точностью при строгой оценке в 60.5 (64 обучение / 58 тест). То же наблюдение, но с другой стороны. Метрика `FLEX` пришла к этому с помощью проверяющих людей. Я пришел к этому, ослабив условия тестирования.

Подумайте, что это значит для таблицы лидеров. Если бенчмарк согласен с людьми только в 62 случаев, то чтобы набрать выше 62 по строгим правилам, вы должны начать воспроизводить ошибки бенчмарка. Вы перестаете учиться писать правильный SQL. Вы начинаете учиться соответствовать специфической, иногда ошибочной интерпретации каждого вопроса в BIRD. Системы с рейтингом 76 закрепили эти ошибки суждения в своем обучении. Они получают более высокие баллы, становясь *хуже* в выполнении реальной задачи.

Поэтому я построил более реалистичную оценку. Я разделил 500 вопросов на тренировочный набор (151 вопрос) и тестовый набор (349 вопросов).

Я использовал тренировочный набор (train) для калибровки оценки: вручную пересматривал ошибки, создавал исправленные «платиновые» ответы там, где «золотой» SQL BIRD был ошибочным, и настраивал правила частичного совпадения. Тестовый набор (test) был контрольным.

Вот как выглядит точность, если смягчать критерии оценки уровень за уровнем:

Уровень оценки (Scoring Tier) Train Test Что добавляется
Только совпадение с Gold (≈ офиц. BIRD) 64.0 58.2 Строгое равенство наборов результатов
+ Платиновые ответы 73.1 58.5 Исправляет известные ошибки в «золотом» SQL BIRD (см. примечание ниже)
+ Допуск форматирования 78.8 65.5 Различия в `DISTINCT`, лишние колонки, округление
+ Судья LLM 94.9 94.4 “Принял бы человек этот ответ?”

Примечание: «Платиновые» исправления существуют только для тренировочного набора, так как я вручную проверил эти 151 вопрос. Вот почему уровень «Платина» почти не меняется на тесте +0.3 pp против +9.1 pp на тренировке). Но посмотрите на уровень с судьей: 94.9 на тренировке и 94.4 на тесте. Разница всего в половину процентного пункта. Оценка держится на контрольной выборке даже без моих исправлений вручную.

Результаты тренировочной выборки (151 вопрос, все 3 модели):

Модель STRICT (≈ BIRD EX) REALISTIC Общая стоимость Вызовы инструментов (P5 / Median / P95)
`Gemini 3 Flash` 68.2 94.0 1.80 3 / 6 / 9
`Claude Opus 4.5` 64.9 95.4 26.37 4 / 6 / 9
`GPT-5.2` 58.9 95.4 6.87 4 / 7 / 12

Результаты тестовой выборки (349 вопросов, 2 модели):

Модель STRICT (≈ BIRD EX) REALISTIC Общая стоимость Вызовы инструментов (P5 / Median / P95)
`Gemini 3 Flash` 60.7 94.6 3.96 4 / 6 / 9
`GPT-5.2` 55.6 94.3 15.32 4 / 7 / 11

*Примечание: `Claude Opus` не запускался на тестовом наборе. После того как все три модели сошлись на ~95% на тренировке, тратить еще 60+, чтобы доказать то же самое на 349 вопросах, показалось нецелесообразным.*

Медианная модель делает 6-7 вызовов инструментов MCP на вопрос при лимите в 10 итераций. Типичный вопрос выглядит так: изучить схему, просмотреть некоторые колонки, набросать запрос, проверить результаты, уточнить, готово. Некоторые модели, такие как `GPT-5.2`, делают несколько вызовов инструментов за итерацию, поэтому его показатель P95, равный 12, превышает лимит итераций.

Все три модели достигают 94-95% при реалистичной оценке, независимо от того, где они начинают при строгой оценке. На тренировочной выборке разрыв между «лучшим» и «худшим» сокращается с 12.6 процентных пунктов до 1.4. На тесте — с 5.1 до 0.3. Берите любую передовую модель.

Бенчмарк иногда ошибается

BIRD — хороший бенчмарк. Но в нем есть баги. Только в тренировочном наборе (151 вопрос) я нашел 49 случаев, где «золотой» SQL явно неверен. Я не проверял вручную тестовый набор, поэтому реальное число для всех 500 вопросов, вероятно, выше.

Вот пример, который мне запомнился. Вопрос просит список школ, чей совокупный балл превышает 1500. «Золотой» SQL проверяет `count` (количество) студентов, набравших более 1500 баллов. Совершенно другой запрос, совершенно другой ответ. Вы читаете вопрос, читаете «правильный» ответ и думаете: подождите, но спрашивали-то не об этом.

Я создал исправленные «платиновые» ответы для этих случаев. В среднем около 14 из 151 вопроса тренировочной выборки для каждой модели совпали с платиновым ответом вместо золотого, добавив 9.1 процентных пунктов.

Людей не волнует форматирование

На тренировочной выборке еще +5.7 pp получается за счет принятия результатов, которые верны по существу, но не проходят проверку на строгое равенство:

  • Лишние колонки (30 случаев): Модель вернула запрошенные данные плюс дополнительный контекст. Человек сказал бы «спасибо, это полезно». Бенчмарк говорит «провал».
  • Несовпадения `DISTINCT` (41 случай): Модель использовала `SELECT DISTINCT`, когда в золотом ответе этого не было, или наоборот. Уникальные значения совпадают идеально. Человек бы даже не заметил.
  • Различия в округлении (3 случая): Золотой ответ 24.67, ответ модели 24.6667. То же число, разная точность.

Ни один из этих ответов не является неверным. Это различия в форматировании, которые важны только для функции сравнения строк.

Человек (LLM)-в-петле (The LLM-in-the-Loop)

Оставшийся разрыв (16 pp на тренировке, 29 pp на тесте) закрывается судьей LLM. Я использовал `Gemini 3 Flash` для проверки каждого «проваленного» ответа с вопросом: *действительно ли этот SQL отвечает на вопрос?*

На тестовой выборке судья выполняет больше тяжелой работы, потому что там нет «платиновых» исправлений для предварительного отлова багов бенчмарка. Что именно он спасал?

Причина Кол-во Что произошло
Больше отфильтровано (Missing rows) 57 Модель отфильтровала строже, чем золотой стандарт, но это обоснованно.
Лишние строки (Extra rows) 33 Модель интерпретировала вопрос более широко.
Близкие значения (Values close) 19 Числовые результаты в пределах допуска.
Пустой результат 14 Модель ничего не вернула, но логика была верной (данных нет).
Пропущенные колонки 11 Возвращено меньше колонок, но ответ на вопрос дан.

Это оценочные суждения. Должен ли запрос «перечислите все школы в районе» включать чартерные школы? Разумные люди могут не согласиться. Строгий бенчмарк выбирает одну интерпретацию и наказывает за все остальные. Судья просто спрашивает, можно ли обосновать интерпретацию модели.

Если вы создаете ИИ-аналитику, это важно. Никто не выпускает продукт text-to-SQL, где пользователь видит сырые результаты без этапа проверки. Всегда есть человек или LLM, проверяющий выходные данные. Эти 94-95% отражают то, как эти продукты работают на самом деле. 58-64% отражают то, как работают бенчмарки.

А как насчет контекста?

Вы могли бы ожидать, что дополнительный контекст поможет. Комментарии к колонкам, описания, подсказки о значении данных. Это интуиция, лежащая в основе семантических слоев и механизмов контекста.

Я протестировал это. Те же 500 вопросов, все модели, с комментариями к колонкам каждой таблицы и без них.

Схема Train Test
Без комментариев 94.9 94.4
С комментариями 96.0 94.6
Дельта 1.1 pp 0.2 pp

Один процентный пункт на тренировке, почти ничего на тесте. В большинстве вопросов правильность не изменилась.

Если разбить по базам данных, становится интересно. Чем сложнее схема, тем больше помогают комментарии (усредненно по train и test):

База данных Базовая точность Эффект комментариев
`debit_card_specializing` 85.5 (самая сложная) 8.7 pp
`european_football_2` 93.2 3.4 pp
`california_schools` 95.7 (самая легкая) 2.9 pp

Комментарии помогают, когда схема действительно запутанная. Таблица `debit_card_specializing` (попробуйте угадать, как выглядит эта схема) получила самый большой прирост. Но схемы с интуитивными названиями и очевидными связями? Там комментарии сделали только хуже. У моделей уже сформировалась правильная ментальная модель, а комментарии внесли шум.

Каждый разработчик знает это о комментариях в коде. Полезны при реальной неоднозначности. Вредны, когда констатируют очевидное. `// увеличить i на 1` еще никому не помогло.

Почему простые модели данных работают

Базы данных BIRD — это не корпоративные хранилища данных. Они простые:

  • 7 таблиц в среднем.
  • 9 внешних ключей в среднем, в основном «один-ко-многим».
  • Ноль связей «многие-ко-многим».
  • Глубина join макс. 2-3 перехода, нет глубоких иерархий.

LLM читают эти схемы так же, как опытный аналитик читает DDL. Они видят таблицу `schools` с колонками `school_name`, `district` и `enrollment`, и они знают, что делать. Внешний ключ от `schools` к `scores`? Они знают, как их соединить (join). Никому не нужен семантический слой, чтобы объяснить, что “enrollment” означает «количество студентов».

Хорошее моделирование данных — это и есть семантический слой. Когда ваши таблицы названы хорошо, а объединения прямолинейны, у LLM есть всё необходимое.

Во что я бы инвестировал в первую очередь

Каждая среда уникальна, но вот как бы я расставил приоритеты, основываясь на том, что увидел:

  1. Начните с модели данных. Чистые таблицы, понятные названия, простые объединения. Если опытный аналитик может посмотреть на вашу схему и понять ее за несколько минут, то и LLM сможет.
  2. Затем добавьте целевой контекст. Комментарии к колонкам и метаданные, но только там, где действительно существует путаница. Документируйте таблицы типа `debit_card_specializing`, а не `schools`.
  3. История запросов идет следом. Она становится важнее по мере усложнения предметной области, особенно для обнаружения недокументированных бизнес-правил (вроде “abnormal GOT > 60”). Базы данных BIRD имеют простые правила. Но я работаю над (проектом) `DABstep`, у которого простая модель данных, но очень сложные правила предметной области. Тот вид знаний, который живет в головах людей, а не в названиях колонок. Там история запросов и подобранный контекст будут значить гораздо больше. Но даже тогда чистая модель данных стоит на первом месте.

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

Начните сейчас

Планка для «данных, готовых к ИИ», ниже, чем вам говорит индустрия.

Вам не нужен “движок контекста”, семантический слой, годы истории запросов или специализированная платформа метаданных. Вам нужна чистая модель данных и LLM. Найдите домен, который готов к этому, и начните там.

Разрыв между «точностью бенчмарка» и «примет ли это человек?» составил 31 pp на тренировочной выборке и 36 pp на тестовой. Это огромный разрыв, и он закрывается в тот момент, когда вы включаете человека или LLM в цикл проверки. Именно так и работает любой продукт ИИ-аналитики.

Если ваша модель данных чиста, начните сегодня. Направьте LLM на вашу схему и задавайте вопросы. Если ваша модель данных не чиста, теперь вы знаете, с чего начать.

***

Итоги статьи

  1. Проблема: Принято считать, что для работы ИИ с базами данных (Text-to-SQL) нужны сложные семантические слои, история запросов и контекст.
  2. Эксперимент: Автор протестировал работу современных LLM (Claude, Gemini, GPT) на известном наборе данных BIRD.
  3. Открытие 1: Формальные бенчмарки занижают качество работы ИИ. Они требуют строгого совпадения SQL-запросов, хотя люди принимают ответы с правильными данными, но другим форматированием (лишние колонки, другой порядок сортировки). Истинная (“реалистичная”) точность моделей достигает 95%, тогда как бенчмарк показывает около 60%.
  4. Открытие 2: “Готовность данных к ИИ” сводится к понятной структуре базы данных. Чистые таблицы, внятные названия колонок и простые связи работают лучше, чем нагромождение комментариев.
  5. Открытие 3: Дополнительные комментарии (контекст) нужны только для реально запутанных схем. В простых случаях они даже мешают, создавая шум.
  6. Вывод: Не тратьте ресурсы на сложные семантические надстройки. Инвестируйте в чистоту модели данных (понятные имена таблиц и полей). Хорошая модель данных — это и есть лучший семантический слой для ИИ.

Битва титанов аналитики реального времени: StarRocks против ClickHouse

В мире больших данных, где счет идет на петабайты, а задержка измеряется миллисекундами, выбор правильного аналитического движка определяет успех продукта. Сегодня мы разберем восходящую звезду StarRocks и классического гиганта ClickHouse, а также посмотрим, как Netflix удалось укротить свои логи на экстремальных скоростях.

Часть 1: Обзор технологий и кейс Netflix

StarRocks: Субсекундная аналитика нового поколения

StarRocks — это высокопроизводительный аналитический движок (MPP database) нового поколения, разработанный для сценариев, где скорость имеет решающее значение. Будучи проектом Linux Foundation, он позиционирует себя как самый быстрый открытый движок запросов для субсекундной аналитики как внутри собственного хранилища, так и поверх архитектуры Data Lakehouse.

Ключевые особенности StarRocks:

  • Универсальность:** Поддерживает почти любые сценарии — от многомерной OLAP-аналитики и realtime-дэшбордов до ad-hoc запросов аналитиков.
  • Скорость:** Использует векторизованный движок исполнения, CBO (Cost-Based Optimizer) и пайплайновый параллелизм, что позволяет обгонять конкурентов на сложных запросах с JOIN-ами.
  • Архитектура:** Native cloud-ready, легко масштабируется горизонтально. Умеет работать “on and off the lakehouse” — то есть быстро читать данные напрямую из S3/HDFS (форматы Parquet, ORC, Iceberg, Hudi) без необходимости их обязательной загрузки внутрь базы.

Кейс Netflix: Как оптимизировать логирование петабайтного масштаба с ClickHouse

*( адаптация материала из блога ClickHouse)* https://clickhouse.com/blog/netflix-petabyte-scale-logging

В Netflix масштаб диктует всё. Инженер Дэниел Муино поделился инсайтами о том, как их система логирования справляется с 5 петабайтами логов ежедневно, обрабатывая в среднем 10.6 миллионов событий в секунду и отвечая на запросы быстрее, чем за секунду.

Для достижения такой производительности потребовалось не просто выбрать правильную базу данных (ClickHouse), но и внедрить три критических инженерных оптимизации.

Архитектура: Горячее и холодное

Netflix использует гибридный подход:

  • Горячий слой (ClickHouse):** Хранит недавние логи, где критична скорость для интерактивной отладки. Данные поступают через Kafka/Kinesis в ClickHouse практически мгновенно.
  • Холодный слой (Apache Iceberg):** Обеспечивает экономичное долговременное хранение исторических данных на S3.
  • Единый API автоматически решает, к какому слою обращаться, скрывая сложность от инженеров.

Результат: логи доступны для поиска через 20 секунд после генерации (при SLA в 5 минут), а сложные аналитические запросы выполняются почти мгновенно.

Три главные оптимизации

1. Ingestion: Свой лексер вместо Regex
Изначально Netflix использовал регулярные выражения для группировки похожих логов (fingerprinting). На скорости 10 млн событий/сек это стало узким местом.

  • Решение:* Команда переписала логику, создав сгенерированный лексер с помощью JFlex.
  • Результат:* Рост пропускной способности в 8-10 раз. Время обработки одного события упало с 216 до 23 микросекунд.

2. Сериализация: Отказ от JDBC
Стандартные JDBC-вставки через Java-клиент создавали оверхед на согласование схем. Переход на низкоуровневый формат `RowBinary` помог, но потребление CPU оставалось высоким.

  • Решение:* Дэниел реверс-инжинирил протокол Go-клиента ClickHouse (который поддерживает нативный формат) и написал собственный энкодер. Он генерирует LZ4-сжатые блоки в нативном протоколе ClickHouse.
  • Результат:* Снижение нагрузки на CPU и памяти при той же пропускной способности.

3. Запросы: Шардирование карт тегов (Tag Maps)
Инженеры Netflix активно используют кастомные теги (фильтры по microservice_id, request_id). Изначально они хранились как `Map(String, String)`. В ClickHouse это реализовано как два параллельных массива, что требует линейного сканирования при поиске. При 25 000 уникальных ключей в час запросы тормозили.

  • Решение:* Шардирование карты. Ключи тегов хешируются в 31 меньшую карту. Запрос сразу “прыгает” в нужный шард вместо перебора всех ключей.
  • Результат:* Время фильтрующих запросов упало с 3 секунд до 1.3, а сложных проекций — с 3 секунд до 700 мс.

Часть 2: ClickHouse vs StarRocks — Битва за Lakehouse

Обе системы являются лидерами в мире OLAP (On-Line Analytical Processing), используют MPP-архитектуру и колоночное хранение. Однако их философия и степень готовности к современной концепции Lakehouse (аналитика данных непосредственно в озере данных без копирования) различаются.

1. Архитектурные корни и специализация

  • ClickHouse:**
    • ДНК:* Изначально создавался для Яндекс.Метрики. Король единой широкой таблицы.
    • Сильная сторона:* Непревзойденная скорость записи и чтения на одной таблице. Идеален для логов (как у Netflix), телеметрии, событийных данных.
    • Слабая сторона:* JOIN-ы (соединения таблиц). ClickHouse умеет их делать, но исторически это не его конек. Оптимизатор запросов долгое время был рудиментарным, требуя от пользователя ручной оптимизации порядка таблиц.
  • StarRocks:**
    • ДНК:* Эволюционировал из Apache Doris. Создавался с прицелом на сложные сценарии аналитики.
    • Сильная сторона:* CBO (Cost-Based Optimizer) уровня Oracle или Teradata. StarRocks блестяще справляется со сложными SQL-запросами, включая многотабличные JOIN-ы “звезда” и “снежинка”.
    • Специфика:* Ориентирован на обновление данных в реальном времени (Primary Key table engine) и векторизованную обработку сложных вычислений.

2. Степень готовности к Lakehouse (Работа с S3, HDFS, Iceberg)

Здесь наблюдается главное стратегическое расхождение.

StarRocks: Native Lakehouse Engine
StarRocks позиционирует себя как движок, который может вообще не хранить данные у себя, а выступать только быстрым вычислительным слоем поверх S3/MinIO.

  • Кэширование:** Имеет продвинутый локальный кэш данных (Local Data Cache), который подтягивает горячие данные из S3 на диски воркеров, обеспечивая скорость, сравнимую с нативным хранением.
  • Каталоги:** Бесшовная интеграция с Hive Metastore, AWS Glue, Iceberg, Hudi, Delta Lake. Вы просто подключаете каталог и пишете `SELECT` к таблицам в S3 без `CREATE TABLE`.
  • Вердикт: StarRocks **полностью готов к Lakehouse. Это один из лучших выборов для сценария “данные лежат в S3 в формате Parquet/Iceberg, а нам нужен быстрый SQL поверх них”.

ClickHouse: Storage First, Lakehouse Second
ClickHouse исторически — это система хранения. Хотя поддержка S3 и Data Lakes активно развивается (особенно в 2024-2025 годах), подход отличается.

  • Интеграция:** ClickHouse может читать из S3 (`s3()` table function или S3 table engine). Поддерживает Iceberg и Hudi.
  • Производительность:** Чтение “холодных” данных из S3 в ClickHouse часто медленнее, чем в StarRocks, из-за особенностей реализации сканирования и работы с метаданными внешних форматов.
  • Кейс Netflix подтверждает: Netflix использует ClickHouse **как горячее хранилище, копируя туда данные. А для лекхоуса (Iceberg) они используют отдельные движки (вероятно, Trino или Spark), а ClickHouse выступает именно как акселератор для свежих данных.
  • Вердикт: ClickHouse движется в сторону Lakehouse (разделение Storage и Compute, S3-backed MergeTree), но его главная суперсила по-прежнему раскрывается, когда данные **импортированы в его родной формат.

Пример использования ClickHouse (из статьи выше)

В примере Netflix мы видим классический паттерн использования ClickHouse, где он силен максимально:

*“ClickHouse находится в сердце системы как горячий слой (hot tier). Он хранит недавние логи, где скорость критична... Для исторических данных Netflix использует Apache Iceberg.”*

Это подтверждает тезис: ClickHouse идеален, когда вы загружаете данные в него (Ingest heavy). StarRocks же часто выигрывает там, где данные уже лежат в озере, и вы не хотите их никуда копировать, либо, когда вам нужны сложные JOIN-ы поверх этих данных.


Итог и рекомендации

Выбор между StarRocks и ClickHouse больше не стоит в плоскости “кто быстрее сканирует одну колонку”. Обе системы феноменально быстры. Вопрос в архитектуре ваших данных.

Рекомендации:

  1. Выбирайте ClickHouse, если:
    • Ваша главная задача — работа с логами, метриками, clickstream (как у Netflix).
    • У вас плоская структура данных (одна широкая таблица), и JOIN-ы редки.
    • Вам нужна максимальная скорость вставки (ingestion) и максимальное сжатие данных на диске.
    • У вас есть ресурсы на инженерию: ClickHouse гибок, но, как показал кейс Netflix, требует “прямых рук” для тонкой настройки (кастомные кодеки, шардирование тегов).
  1. Выбирайте StarRocks, если:
    • Вы строите Data Lakehouse: данные лежат в S3 (Iceberg/Parquet), и вы хотите анализировать их без ETL/копирования.
    • У вас сложная модель данных (схема “Звезда” или “Снежинка”) и много JOIN-ов в запросах.
    • Вам нужны обновления данных (UPSERT/DELETE) в реальном времени с использованием Primary Keys.
    • Вы хотите упростить поддержку и получить оптимизатор запросов, который многое сделает за вас “из коробки”.

Приложение:

Ниже представлен анализ списка компаний, использующих StarRocks. Они разделены по сферам деятельности, а также ранжированы по глубине использования технологии и вкладу в развитие проекта.

1. Сферы деятельности компаний

Вот краткое описание того, чем занимается каждая компания из вашего списка:

Технологии, Интернет и E-commerce:

  • Alibaba:** Крупнейший китайский холдинг электронной коммерции и облачных вычислений.
  • Shopee:** Ведущая платформа электронной коммерции в Юго-Восточной Азии и Тайване.
  • Trip.com:** Одно из крупнейших в мире онлайн-турагентств.
  • Airbnb:** Онлайн-площадка для размещения, поиска и краткосрочной аренды жилья.
  • Xiaohongshu (RedNote):** Китайская социальная сеть и платформа электронной коммерции (аналог Instagram + Pinterest).
  • Zepto:** Сервис быстрой доставки продуктов (quick commerce) из Индии.
  • Naver:** Ведущая южнокорейская интернет-компания (поисковик, карты и др.).

Социальные сети и Медиа:

  • Pinterest:** Фотохостинг, социальная сеть для обмена идеями.
  • Tencent (Games & LLM):** Технологический гигант, владелец WeChat, крупнейший в мире издатель видеоигр.
  • iQiyi:** Крупная китайская платформа онлайн-видео (аналог Netflix).
  • SmartNews:** Агрегатор новостей (популярен в Японии и США).

Финтех и Криптовалюты:

  • Coinbase:** Крупнейшая американская криптовалютная биржа.
  • Intuit:** Американская компания, разработчик финансового ПО (QuickBooks, TurboTax).
  • TRM Labs:** Блокчейн-аналитика, порядочность в криптосфере и compliance.
  • Yuno:** Финтех-оркестратор платежей.

B2B SaaS и Корпоративное ПО:

  • Airtable:** Облачный сервис для работы с базами данных и таблицами (no-code).
  • Celonis:** Лидер в области Process Mining (анализ бизнес-процессов).
  • Cisco:** Мировой лидер в области сетевых технологий и кибербезопасности.
  • Demandbase:** Платформа для ABM-маркетинга (Account-Based Marketing).
  • Eightfold.ai:** Платформа для управления талантами на базе ИИ.
  • Freshа:** Платформа для бронирования услуг в сфере красоты и здоровья.
  • SplitMetrics:** Платформа для A/B тестирования и оптимизации мобильных приложений.
  • Verisoul:** Платформа для выявления фейковых пользователей и ботов.

Транспорт и Логистика:

  • Didi:** Китайский агрегатор такси (аналог Uber).
  • Grab:** Супер-приложение из Юго-Восточной Азии (такси, доставка еды, платежи).

Игры:

  • PlaySimple Games:** Разработчик мобильных словесных игр.

Сельское хозяйство:

  • HerdWatch:** ПО для управления фермерскими хозяйствами.

Энергетика:

  • Haezoom:** Южнокорейская платформа в сфере солнечной энергетики (Energy AI).

Ритейл (Merchandise):

  • Fanatics:** Мировой лидер по продаже лицензионной спортивной атрибутики.

2. Ранжирование по степени использования (Use Case Depth)

Это ранжирование основано на публично доступных кейсах (case studies), объемах данных и критичности систем, переведенных на StarRocks.

Уровень 1: Heavy Users / Mission Critical (Ключевые внедрения)

Эти компании заменили устаревшие хранилища данных (Snowflake, ClickHouse, Druid) на StarRocks для критически важных задач с огромными объемами данных.

  1. Airbnb: Используют StarRocks для метрик реального времени и “умного” ценообразования (Minerva). Огромные объемы данных, строгие требования к задержке.
  2. Tencent (Games & LLM): Один из самых масштабных пользователей. Унифицировали аналитику (заменив Hive/Spark/Druid), что позволило анализировать данные сотен игр в реальном времени.
  3. Trip.com: Полностью отказались от ClickHouse и частично от Hive в пользу StarRocks для ускорения отчетов. Обрабатывают петабайты данных, высокая конкуренция запросов.
  4. Shopee: Используют StarRocks для Data Service (API), ускорив запросы в 3 раза по сравнению с Presto. Критически важно для работы их E-commerce платформы.
  5. Didi: Масштабное использование для логистики в реальном времени и анализа поездок.
  6. Fanatics: Сократили расходы на 90%, перейдя с Snowflake на связку StarRocks + Iceberg.
  7. Coinbase: Заменили Snowflake для аналитики, обращенной к клиенту (customer-facing). Требовались быстрые JOIN-ы на терабайтных масштабах, чего не давали другие системы.

Уровень 2: Strategic Users (Важные продуктовые внедрения)

Компании, использующие StarRocks для конкретных, высоконагруженных продуктов или функций.

  1. Pinterest: Используют для аналитики, но акцент сделан на Lakehouse-архитектуре и join-ах больших таблиц.
  2. Xiaohongshu (RedNote): Аналитика поведения пользователей в реальном времени (user behavior analysis) с высочайшей кардинальностью данных.
  3. Fresha: Аналитика для партнеров (салонов красоты). Важна скорость отклика дэшбордов для тысяч внешних пользователей.
  4. Grab: Аналитика для супер-приложения. Замена Druid/Pinot для более гибких SQL-запросов.
  5. Celonis: Использование в движке Process Mining, где требуются сложные JOIN-операции, с которыми StarRocks справляется лучше колоночных аналогов.

Уровень 3: Adopters (Специфические сценарии)

Компании, использующие StarRocks для внутренних BI-систем, маркетинговой аналитики или замены медленных компонентов.

  • Airtable, Cisco, Intuit, Zepto, PlaySimple Games:** Вероятнее всего, использование для внутренней ускоренной аналитики и BI-отчетов, где традиционные DWH стали слишком медленными или дорогими.

3. Ранжирование по степени влияния на проект (Contribution & Influence)

StarRocks — это Open Source проект. Влияние оценивается по вкладу в код (Pull Requests), участию в техническом комитете (TSC) и архитектурном развитии.

1. Лидеры (Архитекторы и основные контрибьюторы):

  • Alibaba и Tencent:** Эти техногиганты не просто используют проект, они предоставляют огромное количество коммитов, тестируют его на экстремальных нагрузках и формируют roadmap развития. Многие фичи для “реального времени” и интеграции с Data Lake пришли благодаря требованиям и коду инженеров этих компаний.
  • Didi:** Активные контрибьюторы в области стабильности и оптимизации планировщика запросов под высокие нагрузки.
  • Airbnb:** Их вклад значителен в области интеграции с экосистемой данных (например, улучшения для Apache Iceberg и метрик), так как они строят сложные платформы данных (Minerva).

2. Инноваторы (Драйверы конкретных фич):

  • Trip.com: Сильно повлияли на развитие функций для работы с **Data Lakehouse (прямые запросы к Hive/Iceberg без импорта данных), так как их основной кейс — отказ от миграции данных.
  • Shopee: Влияют на развитие функционала **Materialized Views (материализованных представлений), так как активно используют их для ускорения API.
  • Pinterest и Coinbase:** Их кейсы (быстрые JOIN-ы на S3) подталкивают развитие кеширования и оптимизатора для “холодных” данных.

3. Евангелисты (Популяризаторы):

  • Celonis, Fanatics, Grab:** Активно выступают на конференциях, пишут технические блоги о миграции с конкурентов (Snowflake, Druid), тем самым привлекая новых пользователей и валидируя технологию на западном рынке.

ClickHouse — это колоночная аналитическая СУБД с открытым кодом, позволяющая выполнять аналитические запросы в режиме реального времени на структурированных больших данных. Изначально разработанная в Яндексе для Яндекс.Метрики, она стала мировым стандартом для задач логирования, телеметрии и продуктовой аналитики благодаря феноменальной скорости вставки и сжатия данных.

1. Сферы деятельности компаний

Список компаний, использующих ClickHouse, охватывает почти все отрасли, где генерируются “Big Data”.

Технологии, Интернет и Облачные сервисы:

  • Yandex:** Родительская компания. Поисковик, такси, e-commerce, облачные сервисы.
  • Cloudflare:** Глобальная сеть доставки контента (CDN) и защита от DDoS.
  • Uber:** Мировой агрегатор такси и доставки.
  • eBay:** Один из старейших и крупнейших аукционов и маркетплейсов в мире.
  • VK (ВКонтакте):** Крупнейшая социальная сеть в СНГ.
  • GitLab:** Платформа для DevOps и управления жизненным циклом ПО.

Стриминг, Медиа и Развлечения:

  • Spotify:** Глобальный аудио-стриминговый сервис.
  • Netflix:** Крупнейший в мире онлайн-кинотеатр (стриминг видео).
  • Twitch:** Видеостриминговый сервис, специализирующийся на компьютерных играх.
  • Disney+ (Disney Streaming):** Стриминговая платформа медиа-конгломерата Disney.

Финансы и Финтех:

  • Bloomberg:** Поставщик финансовой информации для профессиональных участников рынков.
  • Deutsche Bank:** Крупнейший банковский концерн Германии.
  • Revolut:** Британский финтех-стартап и необанк.

Мониторинг, Observability и SaaS:

  • Datadog:** Платформа мониторинга и безопасности для облачных приложений.
  • Grafana Labs:** Разработчик популярнейшей платформы визуализации данных.
  • Sentry:** Платформа для отслеживания ошибок в приложениях.
  • Segment (Twilio):** Платформа клиентских данных (CDP).

Телеком:

  • Comcast:** Крупнейшая телекоммуникационная компания США.
  • Verizon:** Один из лидеров американского рынка мобильной связи.

---

2. Ранжирование по степени использования (Use Case Depth)

Это ранжирование отражает масштаб данных, критичность системы для бизнеса и сложность архитектуры.

Уровень 1: Heavy Users / Hyper-scale (Экстремальные нагрузки)

Компании, обрабатывающие триллионы строк, где ClickHouse является ядром инфраструктуры.

  1. Cloudflare: Пожалуй, один из самых впечатляющих кейсов в мире. Используют ClickHouse для аналитики HTTP-трафика и DNS-запросов. Обрабатывают десятки миллионов событий в секунду (более 100 млрд строк в день) для предоставления аналитики клиентам в личном кабинете.
  2. Yandex (Метрика): Исторический “reference implementation”. Крупнейшая система веб-аналитики в Европе, работающая на кластерах из сотен серверов. Именно для этой нагрузки (>1 триллиона строк в базе) ClickHouse и был создан.
  3. Uber: Используют ClickHouse для своей платформы логирования (более 4 петабайт данных), заменив Elasticsearch в ряде задач ради экономии ресурсов и скорости.
  4. Lyft: Используют для аналитики поездок и Geo-данных в реальном времени, обрабатывая огромные потоки телеметрии с автомобилей и приложений.
  5. Bytedance (TikTok): (До миграции части нагрузок на другие системы) Один из крупнейших пользователей в Китае, использовавший ClickHouse для анализа поведения пользователей (User Behavior Analysis) на гигантских масштабах.

Уровень 2: Strategic Users (Ключевой компонент продукта)

Компании, которые строят свой основной продукт или критически важные внутренние сервисы на базе ClickHouse.

  1. Sentry: Вся аналитика ошибок и производительности в их SaaS-продукте построена на ClickHouse. Они хранят миллиарды событий ошибок, позволяя разработчикам мгновенно фильтровать их.
  2. GitLab: Используют ClickHouse для feature “Observability” внутри своего продукта, предоставляя пользователям аналитику по их CI/CD пайплайнам.
  3. Spotify: Используют для внутренней аналитики экспериментов (A/B тесты) и логов воспроизведения треков.
  4. eBay: Используют для OLAP-аналитики логов приложений и мониторинга, добиваясь снижения затрат по сравнению с традиционными коммерческими решениями.
  5. Segment: Платформа позволяет клиентам делать сложные выборки по аудитории, и ClickHouse здесь выступает в роли “движка” для мгновенной сегментации пользователей.

Уровень 3: Adopters (Специализированные задачи)

Использование для конкретных департаментов, внутренней бизнес-разведки (BI) или замены старых компонентов.

  • Deutsche Bank:** Анализ рыночных тиков и высокочастотная финансовая аналитика.
  • Comcast:** Мониторинг качества видеопотока и сети.
  • Bloomberg:** Аналитика взаимодействия пользователей с терминалом Bloomberg.

---

3. Ранжирование по степени влияния на проект (Contribution & Influence)

ClickHouse имеет огромное сообщество. Влияние оценивается не только по использованию, но и по вкладу в кодовую базу (PR), разработке драйверов и организации митапов.

1. Создатели и Архитекторы:

  • ClickHouse Inc:** После выделения в отдельную компанию в 2021 году, основные разработчики (включая Алексея Миловидова) работают здесь. Именно они определяют roadmap, развивают ClickHouse Cloud и ядро системы.
  • Yandex:** Исторический создатель. До сих пор вносят огромный вклад, поддерживают свои форки и используют систему на пределе возможностей, что помогает выявлять баги производительности.

2. Технологические Партнеры и Контрибьюторы:

  • Cloudflare:** Внесли огромный вклад в оптимизацию работы с сетью, TLS и безопасность, так как их требования к защищенности и нагрузке экстремальны. Часто пишут глубокие технические статьи о внутренностях ClickHouse.
  • Altinity:** Компания, оказывающая консалтинг и поддержку ClickHouse. Сделали огромный вклад в экосистему Kubernetes (ClickHouse Operator), драйверы и интеграцию с экосистемой Hadoop/MySQL.
  • Contentsquare:** Активно участвуют в оптимизации ядра для специфических аналитических функций (session analysis).

3. Евангелисты Экосистемы:

  • Uber и Lyft:** Публикуют детальные инженерные блоги о том, как переводить логирование с ELK стека на ClickHouse, чем вдохновили сотни других компаний на миграцию.
  • Grafana Labs:** Разрабатывают и поддерживают официальный плагин ClickHouse для Grafana, делая СУБД доступной для визуализации миллионам пользователей.
Earlier Ctrl + ↓