{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Yuriy Gavrilov: posts tagged Database",
    "_rss_description": "Welcome to my personal place for love, peace and happiness 🤖 Yuiry Gavrilov",
    "_rss_language": "en",
    "_itunes_email": "yvgavrilov@gmail.com",
    "_itunes_categories_xml": "",
    "_itunes_image": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic-square@2x.jpg?1643451008",
    "_itunes_explicit": "no",
    "home_page_url": "https:\/\/gavrilov.info\/tags\/database\/",
    "feed_url": "https:\/\/gavrilov.info\/tags\/database\/json\/",
    "icon": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic@2x.jpg?1643451008",
    "authors": [
        {
            "name": "Yuriy Gavrilov - B[u]g - for charity.gavrilov.eth",
            "url": "https:\/\/gavrilov.info\/",
            "avatar": "https:\/\/gavrilov.info\/pictures\/userpic\/userpic@2x.jpg?1643451008"
        }
    ],
    "items": [
        {
            "id": "337",
            "url": "https:\/\/gavrilov.info\/all\/queryflux-universal-sql-proxy-dlya-analiticheskih-dvizhkov\/",
            "title": "QueryFlux: Universal SQL Proxy для аналитических движков",
            "content_html": "<blockquote>\n<p>В этой статье я расскажу, как поднять полноценную инфраструктуру для аналитических запросов, используя <b>QueryFlux<\/b> — высокопроизводительный SQL-прокси на Rust, который умеет принимать запросы по разным протоколам (Trino HTTP, PostgreSQL wire, MySQL wire) и маршрутизировать их на различные бэкенды (Trino, StarRocks, DuckDB, Athena). Мы соберем стек: <b>Trino<\/b> как основной движок, <b>Lakekeeper<\/b> как Iceberg REST-каталог, <b>MinIO<\/b> как S3-хранилище, <b>StarRocks<\/b> как альтернативный MPP-движок, и наконец сам <b>QueryFlux<\/b>, который предоставит единую точку входа для клиентов.<\/p>\n<\/blockquote>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.47.49.png\" width=\"1604\" height=\"942\" alt=\"\" \/>\n<\/div>\n<p>Все конфигурации взяты из реального рабочего проекта, запущенного на macOS с Podman (но совместимы и с Docker). Детально разберем файлы, шаги запуска, решим типичные проблемы, покажем интерфейс управления и сравним QueryFlux с Trino Gateway и другими решениями.<\/p>\n<p><a href=\"https:\/\/github.com\/lakeops-org\/queryflux\/blob\/main\/examples\/full-stack\/docker-compose.yml\">https:\/\/github.com\/lakeops-org\/queryflux\/blob\/main\/examples\/full-stack\/docker-compose.yml<\/a><\/p>\n<hr \/>\n<h3>1. Что такое QueryFlux и зачем он нужен<\/h3>\n<p>Современные data-платформы часто состоят из нескольких движков: Trino для федеративных запросов, StarRocks\/ClickHouse для низкой задержки, DuckDB для ad-hoc аналитики, Athena для serverless-задач. Каждый движок имеет свой wire-протокол, свой диалект SQL и свои настройки аутентификации. Клиенты вынуждены либо подключаться напрямую к каждому движку, создавая $N \\times M$ интеграций, либо использовать «костыли» в коде.<\/p>\n<p><b>QueryFlux<\/b> решает эту проблему, становясь единым шлюзом:<\/p>\n<ul>\n<li>Принимает запросы по протоколам: Trino HTTP, PostgreSQL Wire, MySQL Wire, Arrow Flight SQL.<\/li>\n<li>Маршрутизирует запросы по правилам (протокол, заголовки, regex, Python-скрипты).<\/li>\n<li>Ограничивает конкурентность (через параметр `maxRunningQueries`), ведет очереди, отдает метрики в Prometheus.<\/li>\n<li>Поддерживает аутентификацию (OIDC, static, LDAP) и авторизацию (OpenFGA).<\/li>\n<\/ul>\n<p>Документация: <a href=\"https:\/\/queryflux.dev\">queryflux.dev<\/a><\/p>\n<hr \/>\n<h3>2. Наша лабораторная конфигурация<\/h3>\n<p>Мы развернем следующий стек через `podman-compose` (или `docker-compose`):<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Сервис<\/td>\n<td style=\"text-align: center\">Назначение<\/td>\n<td style=\"text-align: center\">Порт на хосте<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>trino<\/b><\/td>\n<td style=\"text-align: center\">Движок запросов (федерация + Iceberg)<\/td>\n<td style=\"text-align: center\">8081 (прямой доступ)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>starrocks<\/b><\/td>\n<td style=\"text-align: center\">Альтернативный MPP-движок<\/td>\n<td style=\"text-align: center\">9030 (MySQL протокол)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>lakekeeper<\/b><\/td>\n<td style=\"text-align: center\">Iceberg REST-каталог<\/td>\n<td style=\"text-align: center\">8181<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>minio<\/b><\/td>\n<td style=\"text-align: center\">S3-совместимое хранилище (данные Iceberg)<\/td>\n<td style=\"text-align: center\">19000 (API), 19001 (консоль)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>postgres<\/b><\/td>\n<td style=\"text-align: center\">БД метаданных Lakekeeper<\/td>\n<td style=\"text-align: center\">5433<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>queryflux<\/b><\/td>\n<td style=\"text-align: center\">Прокси-сервер<\/td>\n<td style=\"text-align: right\">8080 (Trino), 5434 (PG wire), 3306 (MySQL), 9000 (Admin API), 3000 (Studio UI)<\/td>\n<\/tr>\n<\/table>\n<hr \/>\n<h3>3. Математика планирования нагрузки (ограничение ресурсов)<\/h3>\n<p>Одним из важных аспектов настройки QueryFlux является управление конкурентностью (concurrency limit) через параметр `maxRunningQueries`.<\/p>\n<p>Если мы обозначим лимит конкурентных запросов в группе маршрутизации как N, а среднее время выполнения одного запроса на бэкенде как T (в секундах), то <b>теоретическая максимальная пропускная способность группы<\/b> (Throughput, обозначается как R, в запросах в секунду) рассчитывается так:<\/p>\n<p>R = N \/T<\/p>\n<p>Например, в нашем файле `config.yaml` мы задаем N = 100. Если средний аналитический запрос отрабатывает за T = 2.5 секунды, то пропускная способность нашей Trino-группы составит R = 40 запросов в секунду. Запросы сверх этого лимита попадают в очередь на стороне самого QueryFlux.<\/p>\n<hr \/>\n<h3>4. Конфигурационные файлы<\/h3>\n<p>Создайте папку `queryflux-demo\/examples\/full-stack` и перейдите в нее. Ниже приведены все необходимые файлы.<\/p>\n<p><details><br \/>\n<summary><strong>📄 Показать содержимое файла<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">docker-compose.yml<\/code><\/pre><p>(Полный стек)<\/strong><\/summary><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">name: queryflux-example-full\n\nservices:\n  queryflux:\n    image: ghcr.io\/lakeops-org\/queryflux:latest\n    platform: linux\/amd64\n    ports:\n      - &quot;8080:8080&quot;   # Trino HTTP через QueryFlux\n      - &quot;9000:9000&quot;   # Admin API\n      - &quot;3000:3000&quot;   # QueryFlux Studio\n      - &quot;3306:3306&quot;   # MySQL wire\n      - &quot;5434:5434&quot;   # PostgreSQL wire\n    volumes:\n      - .\/config.yaml:\/etc\/queryflux\/config.yaml:ro\n    environment:\n      RUST_LOG: ${RUST_LOG:-queryflux=info,queryflux_frontend=info}\n    depends_on:\n      postgres:\n        condition: service_healthy\n      trino:\n        condition: service_healthy\n      starrocks:\n        condition: service_healthy\n    restart: unless-stopped\n\n  trino:\n    image: trinodb\/trino:latest\n    platform: linux\/amd64\n    environment:\n      CATALOG_MANAGEMENT: dynamic\n    ports:\n      - &quot;8081:8080&quot;\n    healthcheck:\n      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-sf&quot;, &quot;http:\/\/localhost:8080\/v1\/info&quot;]\n      interval: 10s\n      timeout: 5s\n      retries: 15\n      start_period: 30s\n    volumes:\n      - .\/trino-config\/access-control.properties:\/etc\/trino\/access-control.properties:ro\n\n  starrocks:\n    image: starrocks\/allin1-ubuntu:latest\n    platform: linux\/amd64\n    ports:\n      - &quot;9030:9030&quot;\n      - &quot;8030:8030&quot;\n    healthcheck:\n      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-sf&quot;, &quot;http:\/\/localhost:8030\/api\/health&quot;]\n      interval: 15s\n      timeout: 10s\n      retries: 20\n      start_period: 60s\n\n  postgres:\n    image: postgres:16-alpine\n    platform: linux\/amd64\n    ports:\n      - &quot;5433:5432&quot;\n    environment:\n      POSTGRES_DB: queryflux\n      POSTGRES_USER: queryflux\n      POSTGRES_PASSWORD: queryflux\n    volumes:\n      - queryflux-pg:\/var\/lib\/postgresql\/data\n    healthcheck:\n      test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U queryflux&quot;]\n      interval: 5s\n      timeout: 3s\n      retries: 10\n\n  lakekeeper-db:\n    image: postgres:17\n    platform: linux\/amd64\n    environment:\n      POSTGRES_PASSWORD: postgres\n    healthcheck:\n      test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U postgres -p 5432 -d postgres&quot;]\n      interval: 2s\n      timeout: 10s\n      retries: 10\n      start_period: 10s\n\n  minio:\n    image: minio\/minio:latest\n    platform: linux\/amd64\n    environment:\n      MINIO_ROOT_USER: minio-root-user\n      MINIO_ROOT_PASSWORD: minio-root-password\n    command: [&quot;server&quot;, &quot;--console-address&quot;, &quot;:9001&quot;, &quot;\/data&quot;]\n    ports:\n      - &quot;19000:9000&quot;\n      - &quot;19001:9001&quot;\n    healthcheck:\n      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-f&quot;, &quot;http:\/\/localhost:9000\/minio\/health\/ready&quot;]\n      interval: 2s\n      timeout: 10s\n      retries: 20\n      start_period: 15s\n\n  createbuckets:\n    image: minio\/mc:latest\n    platform: linux\/amd64\n    depends_on:\n      minio:\n        condition: service_healthy\n    restart: on-failure\n    entrypoint: &gt;\n      \/bin\/sh -c &quot;\n      \/usr\/bin\/mc alias set local http:\/\/minio:9000 minio-root-user minio-root-password;\n      \/usr\/bin\/mc mb --ignore-existing local\/warehouse;\n      exit 0;\n      &quot;\n\n  migrate:\n    image: quay.io\/lakekeeper\/catalog:latest-main\n    platform: linux\/amd64\n    pull_policy: always\n    environment:\n      LAKEKEEPER__PG_ENCRYPTION_KEY: dev-key-not-secure\n      LAKEKEEPER__PG_DATABASE_URL_READ: postgresql:\/\/postgres:postgres@lakekeeper-db:5432\/postgres\n      LAKEKEEPER__PG_DATABASE_URL_WRITE: postgresql:\/\/postgres:postgres@lakekeeper-db:5432\/postgres\n    restart: &quot;no&quot;\n    command: [&quot;migrate&quot;]\n    depends_on:\n      lakekeeper-db:\n        condition: service_healthy\n\n  lakekeeper:\n    image: quay.io\/lakekeeper\/catalog:latest-main\n    platform: linux\/amd64\n    pull_policy: always\n    environment:\n      LAKEKEEPER__PG_ENCRYPTION_KEY: dev-key-not-secure\n      LAKEKEEPER__PG_DATABASE_URL_READ: postgresql:\/\/postgres:postgres@lakekeeper-db:5432\/postgres\n      LAKEKEEPER__PG_DATABASE_URL_WRITE: postgresql:\/\/postgres:postgres@lakekeeper-db:5432\/postgres\n    command: [&quot;serve&quot;]\n    ports:\n      - &quot;8181:8181&quot;\n    healthcheck:\n      test: [&quot;CMD&quot;, &quot;\/home\/nonroot\/lakekeeper&quot;, &quot;healthcheck&quot;]\n      interval: 2s\n      timeout: 10s\n      retries: 30\n      start_period: 10s\n    depends_on:\n      migrate:\n        condition: service_completed_successfully\n      lakekeeper-db:\n        condition: service_healthy\n      minio:\n        condition: service_healthy\n      createbuckets:\n        condition: service_completed_successfully\n\n  bootstrap:\n    image: alpine\/curl\n    platform: linux\/amd64\n    tty: true\n    stdin_open: true\n    depends_on:\n      lakekeeper:\n        condition: service_healthy\n    restart: &quot;no&quot;\n    entrypoint: \/bin\/sh\n    command:\n      - -c\n      - |\n        curl -sv -X POST http:\/\/lakekeeper:8181\/management\/v1\/bootstrap \\\n          -H 'Content-Type: application\/json' \\\n          --data '{&quot;accept-terms-of-use&quot;: true}'\n        exit 0\n\n  initialwarehouse:\n    image: alpine\/curl\n    platform: linux\/amd64\n    tty: true\n    stdin_open: true\n    depends_on:\n      lakekeeper:\n        condition: service_healthy\n      bootstrap:\n        condition: service_completed_successfully\n    restart: &quot;no&quot;\n    entrypoint: \/bin\/sh\n    command:\n      - -c\n      - |\n        curl -sv -X POST http:\/\/lakekeeper:8181\/management\/v1\/warehouse \\\n          -H 'Content-Type: application\/json' \\\n          --data @\/config\/create-warehouse.json\n        exit 0\n    volumes:\n      - .\/create-warehouse.json:\/config\/create-warehouse.json:ro\n\n  sentinel:\n    image: alpine\n    platform: linux\/amd64\n    command: [&quot;tail&quot;, &quot;-f&quot;, &quot;\/dev\/null&quot;]\n    depends_on:\n      lakekeeper:\n        condition: service_healthy\n      initialwarehouse:\n        condition: service_completed_successfully\n    healthcheck:\n      test: [&quot;CMD&quot;, &quot;true&quot;]\n      interval: 1s\n      retries: 1\n      start_period: 0s\n\n  data-loader:\n    image: trinodb\/trino:476\n    platform: linux\/amd64\n    profiles: [&quot;loader&quot;]\n    environment:\n      TPCH_SCALE: ${TPCH_SCALE:-tiny}\n    entrypoint: [&quot;\/bin\/bash&quot;, &quot;-c&quot;]\n    command:\n      - |\n        set -euo pipefail\n        sed &quot;s\/FROM tpch\\\\.tiny\\\\.\/FROM tpch.$${TPCH_SCALE}.\/g&quot; \/test-data\/init.sql &gt; \/tmp\/init.run.sql\n        exec trino --server http:\/\/trino:8080 --user loader --file \/tmp\/init.run.sql\n    volumes:\n      - ..\/..\/docker\/fixtures\/init.docker-network.sql:\/test-data\/init.sql:ro\n    depends_on:\n      trino:\n        condition: service_healthy\n      sentinel:\n        condition: service_healthy\n\n  starrocks-catalog-setup:\n    image: mysql:8.0\n    platform: linux\/amd64\n    profiles: [&quot;loader&quot;]\n    entrypoint: [&quot;\/bin\/bash&quot;, &quot;-c&quot;]\n    command: [&quot;mysql -h starrocks -P 9030 -u root --connect-timeout=30 &lt; \/setup\/starrocks-setup.sql&quot;]\n    volumes:\n      - ..\/..\/docker\/fixtures\/starrocks-setup.sql:\/setup\/starrocks-setup.sql:ro\n    depends_on:\n      starrocks:\n        condition: service_healthy\n\nvolumes:\n  queryflux-pg:<\/code><\/pre><p><\/details><\/p>\n<p><details><br \/>\n<summary><strong>📄 Вспомогательные конфигурационные файлы<\/strong><\/summary><\/p>\n<p><b>Файл `config.yaml` (настройки QueryFlux)<\/b>:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">queryflux:\n  externalAddress: http:\/\/localhost:8080\n  frontends:\n    trinoHttp:\n      enabled: true\n      port: 8080\n    postgresWire:\n      enabled: true\n      port: 5434\n  persistence:\n    type: inMemory\n\nclusters:\n  trino-1:\n    engine: trino\n    endpoint: http:\/\/trino:8080\n    enabled: true\n    auth:\n      type: basic\n      username: trino\n      password: &quot;&quot;\n\nclusterGroups:\n  trino-default:\n    enabled: true\n    maxRunningQueries: 100\n    members: [trino-1]\n\nrouters:\n  - type: protocolBased\n    trinoHttp: trino-default\n    postgresWire: trino-default\n\nroutingFallback: trino-default<\/code><\/pre><p><b>Файл `trino-config\/access-control.properties`<\/b>:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">access-control.name=allow-all<\/code><\/pre><blockquote>\n<p>Этот файл монтируется в `trino` и разрешает имперсонацию и чтение системных таблиц – иначе статистика в QueryFlux Studio не будет работать.<\/p>\n<\/blockquote>\n<p><b>Файл `.\/create-warehouse.json` (инициализация warehouse Lakekeeper)<\/b>:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">{\n  &quot;warehouse-name&quot;: &quot;test_warehouse&quot;,\n  &quot;project-id&quot;: &quot;00000000-0000-0000-0000-000000000000&quot;,\n  &quot;storage-profile&quot;: {\n    &quot;type&quot;: &quot;s3&quot;,\n    &quot;bucket&quot;: &quot;warehouse&quot;,\n    &quot;endpoint&quot;: &quot;http:\/\/minio:9000&quot;,\n    &quot;region&quot;: &quot;us-east-1&quot;,\n    &quot;path-style-access&quot;: true,\n    &quot;flavor&quot;: &quot;minio&quot;,\n    &quot;sts-enabled&quot;: false\n  },\n  &quot;storage-credential&quot;: {\n    &quot;type&quot;: &quot;s3&quot;,\n    &quot;credential-type&quot;: &quot;access-key&quot;,\n    &quot;aws-access-key-id&quot;: &quot;minio-root-user&quot;,\n    &quot;aws-secret-access-key&quot;: &quot;minio-root-password&quot;\n  }\n}<\/code><\/pre><p><\/details><\/p>\n<hr \/>\n<h3>5. Запуск стека и проверка<\/h3>\n<p>Запускаем весь стек в фоновом режиме:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">cd examples\/full-stack\npodman-compose up -d --wait<\/code><\/pre><h4>5.1. Тест прямого доступа к Trino<\/h4>\n<pre class=\"e2-text-code\"><code class=\"\">curl -X POST http:\/\/localhost:8081\/v1\/statement \\\n  -H 'X-Trino-User: test' \\\n  -d 'SELECT 1'<\/code><\/pre><h4>5.2. Тест через QueryFlux (PostgreSQL wire)<\/h4>\n<p>Подключимся через стандартный клиент `psql` к порту `5434`, который прослушивает QueryFlux:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">psql -h localhost -p 5434 -U trino -d trino<\/code><\/pre><p>Сначала выполним простой запрос для проверки работоспособности протокола:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">SELECT 42;<\/code><\/pre><p>А теперь проверим аналитический потенциал стека. Выполним тяжелый запрос к таблице `call_center` в БД Iceberg, сгенерированной по стандарту TPC-DS:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">SELECT cc_call_center_sk, cc_call_center_id, cc_rec_start_date, cc_rec_end_date, \n       cc_closed_date_sk, cc_open_date_sk, cc_name, cc_class, cc_employees, \n       cc_sq_ft, cc_hours, cc_manager, cc_mkt_id, cc_mkt_class, cc_mkt_desc, \n       cc_market_manager, cc_division, cc_division_name, cc_company, \n       cc_company_name, cc_street_number, cc_street_name, cc_street_type, \n       cc_suite_number, cc_city, cc_county, cc_state, cc_zip, cc_country, \n       cc_gmt_offset, cc_tax_percentage\nFROM tpcds.sf10.call_center;<\/code><\/pre><p>*Скриншот успешного выполнения запроса через psql*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.35.png\" width=\"1286\" height=\"1960\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 1 – Запрос `SELECT count(*) FROM system.runtime.queries` успешно выполняется через QueryFlux, статистика сразу же фиксируется и видна в Studio.*<\/div>\n<\/div>\n<h4>5.3. Проверка QueryFlux Studio<\/h4>\n<p>Откройте браузер и перейдите на `<a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a>`. Логин по умолчанию: `admin` \/ `admin`.<\/p>\n<p>*Главная панель (Dashboard)*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.47.png\" width=\"1706\" height=\"728\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 2 – Дашборд QueryFlux Studio: количество запросов, ошибки, средняя длительность, статус кластеров.*<\/div>\n<\/div>\n<p>*Список кластеров*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.55.png\" width=\"1534\" height=\"694\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 3 – Страница кластеров: виден наш кластер `trino-1`, его группа `trino-default`, состояние и уровень загрузки.*<\/div>\n<\/div>\n<p>*Группы кластеров*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.03.png\" width=\"1704\" height=\"892\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 4 – Управление группами: здесь можно задать ограничение `maxRunningQueries`, список участников и стратегии балансировки. Пока группы инициализируются из in-memory конфигурации.*<\/div>\n<\/div>\n<p>*Скрипты (translation fixups)*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.14.png\" width=\"1398\" height=\"694\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 5 – Скрипты для трансляции диалектов SQL “на лету” (в этой демке не используются).*<\/div>\n<\/div>\n<p>*Guardrails (ограничения)*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.34.png\" width=\"1264\" height=\"878\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 6 – Глобальные и групповые guardrails для инспекции и фильтрации SQL перед отправкой в движок.*<\/div>\n<\/div>\n<p>*Протоколы (frontends)*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.47.png\" width=\"1540\" height=\"776\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 7 – Включённые фронтенды: Trino HTTP (8080) и PostgreSQL wire (5434).*<\/div>\n<\/div>\n<p>*Маршрутизация*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.56.png\" width=\"1408\" height=\"706\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 8 – Правила маршрутизации: `protocolBased` направляет Trino HTTP и PostgreSQL wire в нашу группу `trino-default`.*<\/div>\n<\/div>\n<p>*Admin API (Swagger)*<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.02.06.png\" width=\"1490\" height=\"1720\" alt=\"\" \/>\n<div class=\"e2-text-caption\">*Рис. 9 – Документация Admin API: эндпоинты для управления кластерами, группами, конфигурациями и получения статистики.*<\/div>\n<\/div>\n<hr \/>\n<h3>6. Решение типичных проблем<\/h3>\n<p><details><br \/>\n<summary><strong>🐞 1. Ошибка<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">internal libpod error<\/code><\/pre><p>для одноразовых контейнеров на macOS<\/strong><\/summary><br \/>\nПричина: podman-compose на macOS иногда имеет баг с `tty` и `stdin_open`.<br \/>\nРешение: Параметры уже добавлены в наш `docker-compose.yml`, но если баг не ушел, выполните инициализацию Lakekeeper вручную:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">podman run --rm --network queryflux-example-full_default alpine\/curl \\\n  -X POST http:\/\/lakekeeper:8181\/management\/v1\/bootstrap \\\n  -H 'Content-Type: application\/json' \\\n  -d '{&quot;accept-terms-of-use&quot;: true}'<\/code><\/pre><p><\/details><\/p>\n<p><details><br \/>\n<summary><strong>🐞 2. PostgreSQL Extended Query Protocol<\/strong><\/summary><br \/>\nQueryFlux поддерживает только <b>Simple Query Protocol<\/b> (сообщение `Q`). Extended Query (Parse\/Bind\/Execute) не поддерживается.<\/p>\n<ul>\n<li>`psql` работает “из коробки”.<\/li>\n<li>JDBC-драйверы: добавьте параметр `prepareThreshold=0` в строку подключения, чтобы переключиться в Simple Query режим.  <br \/>\nПример:<\/li>\n<\/ul>\n<pre class=\"e2-text-code\"><code class=\"\">jdbc:postgresql:\/\/localhost:5434\/trino?prepareThreshold=0<\/code><\/pre><p><\/details><\/p>\n<p><details><br \/>\n<summary><strong>🐞 3. Ошибка<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Access Denied: User trino cannot impersonate user queryflux-running-query-reconcile<\/code><\/pre><p><\/strong><\/summary><br \/>\nПричина: Trino не разрешает имперсонацию для системных запросов QueryFlux.<br \/>\nРешение: Мы добавили файл `access-control.properties` со свойством `access-control.name=allow-all`. После этого статистика в Studio заработала (см. Рис. 1 и Рис. 2).<br \/>\n<\/details><\/p>\n<hr \/>\n<h3>7. Мониторинг и управление<\/h3>\n<p>QueryFlux предоставляет три основных интерфейса для наблюдения:<\/p>\n<ul>\n<li><b>QueryFlux Studio<\/b> (порт 3000) – веб-интерфейс для просмотра истории запросов, управления кластерами, группами, маршрутами, скриптами и guardrails.<\/li>\n<li><b>Admin API<\/b> (порт 9000) – REST API для автоматизации (логин: admin\/admin). Документация OpenAPI доступна на `\/docs`.<\/li>\n<li><b>Prometheus метрики<\/b> (порт 9000\/metrics) – стандартные метрики для интеграции с Grafana.<\/li>\n<\/ul>\n<p>Рекомендуемая практика: для production используйте `persistence: postgres`, чтобы конфигурация групп и маршрутов сохранялась при перезапусках, а история запросов накапливалась.<\/p>\n<hr \/>\n<h3>8. Сравнение QueryFlux с альтернативами<\/h3>\n<h4>8.1. Trino Gateway (официальный)<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Характеристика<\/td>\n<td style=\"text-align: center\">QueryFlux<\/td>\n<td style=\"text-align: center\">Trino Gateway<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Поддерживаемые протоколы клиента<\/b><\/td>\n<td style=\"text-align: center\">Trino HTTP, PostgreSQL wire, MySQL wire, Arrow Flight SQL<\/td>\n<td style=\"text-align: center\">Только Trino HTTP<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Бэкенды<\/b><\/td>\n<td style=\"text-align: center\">Trino, DuckDB, StarRocks, Athena, ClickHouse (planned)<\/td>\n<td style=\"text-align: center\">Только Trino<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Маршрутизация<\/b><\/td>\n<td style=\"text-align: center\">По протоколу, заголовкам, тегам, regex, Python скриптам<\/td>\n<td style=\"text-align: center\">По весам, группам, header `X-Trino-Routing-Group`<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>SQL трансляция<\/b><\/td>\n<td style=\"text-align: center\">Да (sqlglot) – из PostgreSQL в Trino и наоборот<\/td>\n<td style=\"text-align: center\">Нет<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Конкурентность и очереди<\/b><\/td>\n<td style=\"text-align: center\">`maxRunningQueries` на группу, очередь на прокси, spillover<\/td>\n<td style=\"text-align: center\">`maxConcurrentQueries` на кластер, очереди нет<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Auth\/AuthZ<\/b><\/td>\n<td style=\"text-align: center\">OIDC, LDAP, Static, OpenFGA<\/td>\n<td style=\"text-align: center\">Базовая поддержка `X-Trino-User`<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Метрики<\/b><\/td>\n<td style=\"text-align: center\">Prometheus, Grafana, Admin API, Studio<\/td>\n<td style=\"text-align: center\">Prometheus (JMX), менее развит<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>GUI управления<\/b><\/td>\n<td style=\"text-align: center\">Полноценный веб-интерфейс (Studio)<\/td>\n<td style=\"text-align: center\">Отсутствует (только конфигурация API)<\/td>\n<\/tr>\n<\/table>\n<p><b>Плюсы QueryFlux:<\/b> гетерогенность (один шлюз на разные виды движков), гибкая маршрутизация, встроенный перевод диалектов, PostgreSQL wire, наличие красивого веб-интерфейса.<br \/>\n<b>Минусы:<\/b> молодой проект (версия 0.1.2), не поддерживается Extended Query Protocol для PostgreSQL, требует настройки доступа к системным таблицам Trino.<\/p>\n<h4>8.2. Другие альтернативы<\/h4>\n<ul>\n<li><b>Trino + многокаталожность<\/b> – простейшее решение, но требует доработки приложений для переключения на trino диалект.<\/li>\n<li><b>Apache Linkis<\/b> – тяжеловесный ETL-ориентированный шлюз, не подходит для лёгкой ad-hoc аналитики.<\/li>\n<li><b>Nginx + Lua + sqlglot<\/b> – сложно поддерживать, требует глубокой кастомной разработки.<\/li>\n<li><b>Коммерческие решения (Starburst, Dremio)<\/b> – дорогостоящие, но предоставляют готовую маршрутизацию, закрытый код и полноценный SLA. но 100% всего не решает так как это готовые коробки. явно захочется что-то под себя подкрутить.<\/li>\n<\/ul>\n<p>и еще много с акцентов на gateway: Hoop.dev кстати интересный и GatewayD<\/p>\n<ul>\n<li>GatewayD и ProxySQL: Не заменяют Trino, но отлично решают вашу задачу с логированием. GatewayD работает с PostgreSQL и может проверять запросы через Casbin, а ProxySQL предоставляет детальное логирование запросов (время, строки, IP и т.д.). Логирование — есть (аудит запросов), диалект Postgres — полный, подключение к 90 БД — сложно (нужно настраивать 90 подключений).<\/li>\n<li>Mammoth и JumpWire: Специализированные прокси для PostgreSQL. Первый упрощает аудит, логируя каждую команду, второй позволяет гибко настраивать политики доступа и маскировать данные. Логирование — есть, диалект Postgres — полный, подключение к 90 БД — сложно (на каждый экземпляр нужен свой прокси).<\/li>\n<li>Hoop.dev: Платформа для контролируемого доступа к базам данных с сильным акцентом на аудит и безопасность. Логирует все: от попыток входа до полного текста запросов и даже планов выполнения. Логирование — детальное, диалект Postgres — полный, подключение к 90 БД — сложно (требует развёртывания на каждую базу).<\/li>\n<li>Уже посмотрели QueryFlux: Это решение ближе всего к Trino, но работает как высокоуровневый шлюз. На входе может принимать запросы через “PostgreSQL wire”, а на выходе автоматически транслировать диалект под Trino, Clickhouse и другие системы. Логирование — ограниченное, диалект Postgres — только как входной интерфейс (запросы уходят в Trino), подключение к 90 БД — замена Trino (шлюз к 90 разным источникам).<\/li>\n<li>SQL Gateway (CData): Позволяет представить любые ODBC-источники как виртуальную PostgreSQL или SQL Server базу. Логирование — только общее, диалект Postgres — виртуальный (эмуляция), подключение к 90 БД — сложно (настройка ODBC).<\/li>\n<li>Cloud Service Gateways (Infisical и др.): Специализированные облачные решения. Обещают централизованный доступ и аудит, но их возможности нативных диалектов сильно привязаны к конкретному провайдеру.<\/li>\n<li>Native PostgreSQL Gateways: Как сборник технологий (например, PgCat), из которых можно построить своё решение. Позволяет гибко настраивать подключения и логи, но требует ручной сборки и высокой квалификации.<br \/>\nИнтеграция с Keycloak: К сожалению, прямой интеграции с Keycloak для аутентификации SQL-запросов практически нет. Keycloak используется для аутентификации доступа к веб-интерфейсам административных консолей, но не для самих SQL-клиентов. Исключение — GatewayD, который, хотя и не интегрируется с Keycloak, позволяет реализовать схожую логику через Casbin.<\/li>\n<\/ul>\n<p><b>Вывод:<\/b> QueryFlux идеален, если у вас уже есть несколько движков и вы хотите дать единую точку входа для бизнес-пользователей и аналитиков (особенно тех, кто привык к `psql`). Для production, где критична поддержка prepare-statements, стоит использовать Trino JDBC напрямую или использовать дополнительный прокси (например, `trino-pg-gateway`).<\/p>\n<hr \/>\n<h3>9. Итоги и рекомендации<\/h3>\n<p>Мы успешно запустили полноценный аналитический стек с Lakekeeper (Iceberg), Trino и StarRocks, а QueryFlux обеспечил единый вход через HTTP и PostgreSQL wire. Ключевые достижения:<\/p>\n<ul>\n<li>✅ QueryFlux принимает Trino HTTP и PostgreSQL wire запросы, направляя их в Trino.<\/li>\n<li>✅ Клиент `psql` выполняет сложные `SELECT`-запросы к Iceberg таблицам (даже TPC-DS) через порт 5434.<\/li>\n<li>✅ Статистика в Studio отображается корректно.<\/li>\n<li>✅ Маршрутизация по протоколу (`protocolBased`) работает как задумано.<\/li>\n<li>✅ Веб-интерфейс Studio даёт полный контроль над кластерами, группами, маршрутами и скриптами.<\/li>\n<\/ul>\n<p><b>Рекомендации для production:<\/b><\/p>\n<ol start=\"1\">\n<li>Замените `persistence: inMemory` на `persistence: postgres` и настройте репликацию БД конфигурации (чтобы не терять историю и настройки).<\/li>\n<li>Включите аутентификацию OIDC (Keycloak) и авторизацию OpenFGA для разграничения доступа к группам кластеров.<\/li>\n<li>Рассчитайте `maxRunningQueries` по формуле N = R \\times T, исходя из планируемой нагрузки и SLA.<\/li>\n<li>Для PostgreSQL-клиентов с GUI (DataGrip\/DBeaver) используйте параметр `prepareThreshold=0` (через JDBC) или переключитесь на официальный Trino JDBC драйвер.<\/li>\n<li>Настройте сбор метрик в Prometheus и дашборды Grafana для мониторинга длины очередей и задержек.<\/li>\n<\/ol>\n<blockquote>\n<p><b>Заключение:<\/b> QueryFlux — очень перспективный и многообещающий инструмент для построения унифицированного доступа к аналитическим движкам. Несмотря на молодость, он уже пригоден для некоторых сценариев, особенно если вы готовы ограничиться simple query protocol при использовании PostgreSQL wire. В связке с Iceberg-каталогами и объектным хранилищем он образует мощную open-source альтернативу дорогим коммерческим решениям.<\/p>\n<\/blockquote>\n",
            "date_published": "2026-06-12T21:15:13+03:00",
            "date_modified": "2026-06-12T21:13:11+03:00",
            "tags": [
                "big data",
                "Data",
                "Database"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.47.49.png",
            "_date_published_rfc2822": "Fri, 12 Jun 2026 21:15:13 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "337",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.47.49.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.35.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.47.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.00.55.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.03.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.14.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.34.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.47.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.01.56.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2026-06-12-v-20.02.06.png"
                ]
            }
        },
        {
            "id": "305",
            "url": "https:\/\/gavrilov.info\/all\/reyting-open-source-grafovyh-subd-dlya-adtech\/",
            "title": "Рейтинг Open Source Графовых СУБД для AdTech",
            "content_html": "<p>Для задач <b>AdTech сегментации<\/b> (профилирование пользователей, identity resolution, поиск look-alike аудиторий) набор требований к графовой базе данных специфичен: нужна высокая скорость операций чтения\/записи (real-time bidding\/serving) и горизонтальная масштабируемость (миллиарды событий и связей).<\/p>\n<p>Учитывая популярность текущего стека (<b>ClickHouse, Trino, Qdrant<\/b>), идеальная графовая база должна уметь интегрироваться в аналитический контур (через Trino или прямые коннекторы) и дополнять ClickHouse (который хранит логи событий), взяв на себя хранение топологии связей.<\/p>\n<p>Ниже представлен небольшой обзор и рейтинг Open Source решений на 2024-2025 год с фокусом на масштабируемость.<\/p>\n<hr \/>\n<h4>Рейтинг Open Source Графовых СУБД для AdTech<\/h4>\n<p>Разделим 12 решений на 3 эшелона по пригодности для высоконагруженной сегментации.<\/p>\n<h5>1 эшелон: Лидеры производительности и масштабирования (Native Distributed)<\/h5>\n<p>Эти базы изначально создавались для кластеров и больших объемов данных.<\/p>\n<p><b>1. NebulaGraph<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Native Distributed Graph Database.<\/li>\n<li><b>Язык запросов:<\/b> nGQL (SQL-подобный).<\/li>\n<li><b>Архитектура:<\/b> Разделение Compute (GraphD) и Storage (StorageD). Shared-nothing.<\/li>\n<li><b>Плюсы для вас:<\/b> Это топ-1 выбор для AdTech масштаба Tencent или Meituan. Спокойно переваривает сотни миллиардов вершин и триллионы ребер. Обеспечивает миллисекундный отклик при обходе графа (hops) на большую глубину.<\/li>\n<li><b>Минусы:<\/b> Более крутая кривая обучения, чем у Neo4j. Сообщество меньше, но растет.<\/li>\n<li><b>Связь со стеком:<\/b> Отлично дополнит ClickHouse (CH хранит атрибуты, Nebula — связи). Есть коннекторы для Spark\/Flink. А через Spark можно дойти до Trino.<\/li>\n<\/ul>\n<p><b>2. Dgraph<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Native Distributed Graph.<\/li>\n<li><b>Язык запросов:<\/b> GraphQL (модифицированный DQL).<\/li>\n<li><b>Архитектура:<\/b> Распределенная, использует BadgerDB (KV store) под капотом. Поддерживает шардинг и репликацию “из коробки” в open source версии.<\/li>\n<li><b>Плюсы:<\/b> Горизонтальное масштабирование. Очень удобна для фронтенд-разработчиков благодаря GraphQL. Высокая пропускная способность.<\/li>\n<li><b>Минусы:<\/b> Специфичный язык запросов, если вы привыкли к SQL\/Cypher. В последние годы темпы разработки ядра немного снизились относительно конкурентов.<\/li>\n<\/ul>\n<p><b>3. Memgraph<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> In-Memory Graph Database (написана на C++).<\/li>\n<li><b>Язык запросов:<\/b> Cypher (совместим с Neo4j).<\/li>\n<li><b>Архитектура:<\/b> Работает в оперативной памяти (с возможностью сброса на диск).<\/li>\n<li><b>Плюсы:<\/b> <b>Самая быстрая<\/b> для задач реального времени (вычисление фичей для RTB). Полная совместимость с экосистемой Neo4j (драйверы, протокол Bolt). Поддерживает Python\/Rust процедуры. Отличная работа с Streaming данными (Kafka).<\/li>\n<li><b>Минусы:<\/b> Ограничена объемом RAM (хотя есть disk-spill, это снижает скорость).<\/li>\n<li><b>Связь со стеком:<\/b> Отлично стыкуется с моделями AI (Qdrant), так как позиционируется для “Graph AI”.<\/li>\n<\/ul>\n<h5>2 эшелон: Классика и Универсалы<\/h5>\n<p><b>4. Neo4j (Community Edition)<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Native Graph.<\/li>\n<li><b>Язык:<\/b> Cypher (стандарт индустрии).<\/li>\n<li><b>Плюсы:<\/b> Огромное сообщество, лучшая документация, куча плагинов (APOC).<\/li>\n<li><b>Главный минус для AdTech:<\/b> Open Source версия (Community) ограничена <b>одним узлом<\/b>. Нет встроенного кластеризации и шардинга (доступно только в Enterprise за большие деньги). Для “технического задела на вырост” в Open Source варианте — это бутылочное горлышко.<\/li>\n<\/ul>\n<p><b>5. ArangoDB<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Multi-model (Graph, Document, Key\/Value).<\/li>\n<li><b>Язык:<\/b> AQL (похож на SQL).<\/li>\n<li><b>Плюсы:<\/b> Гибкость. Можно хранить сложные JSON-документы (как в Mongo) и связывать их.<\/li>\n<li><b>Минусы:<\/b> При глубоких обходах графа (“друзья друзей друзей”) проигрывает специализированным Native Graph базам по скорости. Это компромиссное решение.<\/li>\n<\/ul>\n<p><b>6. JanusGraph<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Layered Graph Database.<\/li>\n<li><b>Плюсы:<\/b> Работает поверх мощных бэкендов (Cassandra, HBase, ScyllaDB) и использует Elasticsearch для индексации. Масштабируемость ограничена только бэкендом.<\/li>\n<li><b>Минусы:<\/b> Очень “тяжелая” инфраструктура (JVM based). Сложна в настройке и эксплуатации. Медленнее на простых запросах из-за сетевых хопов между слоями. Часто считается “устаревающей” архитектурой по сравнению с Nebula\/Dgraph.<\/li>\n<\/ul>\n<p><b>7. Apache AGE (PostgreSQL Extension)<\/b><\/p>\n<ul>\n<li><b>Тип:<\/b> Extension.<\/li>\n<li><b>Суть:<\/b> Превращает PostgreSQL в графовую БД с поддержкой Cypher.<\/li>\n<li><b>Плюсы:<\/b> Если вы знаете Postgres, вы знаете AGE. Не нужно новой инфраструктуры.<\/li>\n<li><b>Минусы:<\/b> Производительность ограничена движком Postgres. Сложно масштабировать горизонтально на запись (проблема шардинга PG).<\/li>\n<\/ul>\n<h5>3 эшелон: Нишевые и Новые игроки<\/h5>\n<p><b>8. HugeGraph<\/b> (Baidu) — аналог JanusGraph, популярен в Китае, очень мощный, но документация местами страдает.<br \/>\n<b>9. OrientDB<\/b> — мультимодельная, была популярна, но сейчас развитие замедлилось.<br \/>\n<b>10. FalkorDB<\/b> — форк закрывшегося RedisGraph (Redis module). Очень быстрый, использует разреженные матрицы. Интересен, если уже есть Redis.<br \/>\n<b>11. Cayley<\/b> — написана на Go (Google), простая, работает с триплетами (Linked Data), но для сложной AdTech логики может не хватить функционала.<br \/>\n<b>12. TerminusDB<\/b> — интересная база с концепцией “Git для данных”, но специфична для версионирования знаний, а не высоконагруженной сегментации.<\/p>\n<h4>Сравнительная таблица (ТОП-7 для выбора)<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">СУБД<\/td>\n<td style=\"text-align: center\">Язык запросов<\/td>\n<td style=\"text-align: center\">Архитектура<\/td>\n<td style=\"text-align: center\">Масштабирование (Open Source)<\/td>\n<td style=\"text-align: center\">Скорость (Read\/Traverse)<\/td>\n<td style=\"text-align: center\">Сложность эксплуатации<\/td>\n<td style=\"text-align: center\">Идеально для<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>NebulaGraph<\/b><\/td>\n<td style=\"text-align: center\">nGQL (SQL-like)<\/td>\n<td style=\"text-align: center\">Distributed Native<\/td>\n<td style=\"text-align: center\"><b>Отличное<\/b> (Sharding+Replication)<\/td>\n<td style=\"text-align: center\">🔥 Очень высокая<\/td>\n<td style=\"text-align: center\">Средняя\/Высокая<\/td>\n<td style=\"text-align: center\">Big Data, AdTech, Fraud<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Memgraph<\/b><\/td>\n<td style=\"text-align: center\">Cypher<\/td>\n<td style=\"text-align: center\">In-Memory (C++)<\/td>\n<td style=\"text-align: center\">Вертикальное \/ Репликация<\/td>\n<td style=\"text-align: center\">🚀 <b>Топ-1 (Low Latency)<\/b><\/td>\n<td style=\"text-align: center\">Низкая (как Docker)<\/td>\n<td style=\"text-align: center\">Real-time features, Streaming<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Dgraph<\/b><\/td>\n<td style=\"text-align: center\">GraphQL<\/td>\n<td style=\"text-align: center\">Distributed Native<\/td>\n<td style=\"text-align: center\"><b>Отличное<\/b><\/td>\n<td style=\"text-align: center\">Высокая<\/td>\n<td style=\"text-align: center\">Средняя<\/td>\n<td style=\"text-align: center\">App Backend, 360 Customer View<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Neo4j (CE)<\/b><\/td>\n<td style=\"text-align: center\">Cypher<\/td>\n<td style=\"text-align: center\">Native<\/td>\n<td style=\"text-align: center\"><b>Нет<\/b> (только 1 нода)<\/td>\n<td style=\"text-align: center\">Высокая (локально)<\/td>\n<td style=\"text-align: center\">Низкая<\/td>\n<td style=\"text-align: center\">R&D, малые проекты<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>ArangoDB<\/b><\/td>\n<td style=\"text-align: center\">AQL<\/td>\n<td style=\"text-align: center\">Multi-model<\/td>\n<td style=\"text-align: center\">Хорошее (Cluster mode)<\/td>\n<td style=\"text-align: center\">Средняя<\/td>\n<td style=\"text-align: center\">Средняя<\/td>\n<td style=\"text-align: center\">Гибридные данные (Docs+Graph)<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>JanusGraph<\/b><\/td>\n<td style=\"text-align: center\">Gremlin<\/td>\n<td style=\"text-align: center\">Layered (over NoSQL)<\/td>\n<td style=\"text-align: center\">Бесконечное (зависит от Backend)<\/td>\n<td style=\"text-align: center\">Низкая\/Средняя<\/td>\n<td style=\"text-align: center\">☠️ Высокая<\/td>\n<td style=\"text-align: center\">Если уже есть HBase\/Cassandra<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Apache AGE<\/b><\/td>\n<td style=\"text-align: center\">Cypher<\/td>\n<td style=\"text-align: center\">Postgres Ext<\/td>\n<td style=\"text-align: center\">Только Read Replicas<\/td>\n<td style=\"text-align: center\">Средняя<\/td>\n<td style=\"text-align: center\">Низкая (если знают PG)<\/td>\n<td style=\"text-align: center\">Гибрид SQL + Graph<\/td>\n<\/tr>\n<\/table>\n<h4>Интеграция с текущим стеком (Qdrant, Trino или ClickHouse)<\/h4>\n<ol start=\"1\">\n<li><b>Qdrant + Graph DB = GraphRAG \/ Semantic Search:<\/b>\n<ul>\n  <li>Сегментация пользователей часто требует поиска не только по связям (“кто кликал то же, что и я”), но и по похожести векторов (“чей профиль похож на мой”).<\/li>\n  <li>Memgraph<b> и **Neo4j<\/b> имеют встроенные модули для работы с векторами, но так как у вас уже есть <b>Qdrant<\/b>, вам нужна база, которая *не пытается заменить Qdrant*, а позволяет хранить ID векторов в узлах графа.<\/li>\n  <li>NebulaGraph** позволяет хранить embedding в свойствах узла, но поиск лучше делегировать Qdrant.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Trino:<\/b>\n<ul>\n  <li>Вам захочется делать SQL-запросы сразу к ClickHouse (события) и Графу (профиль).<\/li>\n  <li>У <b>Neo4j<\/b> и <b>NebulaGraph<\/b> есть коннекторы, позволяющие Trino (через JDBC или нативные коннекторы) запрашивать данные. Это мощнейшая связка для аналитиков. Отдельно нативного конектора к Trino пока не найти, но скоро может появится поддержка iceberg <a href=\"https:\/\/github.com\/vesoft-inc\/nebula\/discussions\/5902\">https:\/\/github.com\/vesoft-inc\/nebula\/discussions\/5902<\/a> или пока можно использоваться связку через Spark.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>ClickHouse:<\/b>\n<ul>\n  <li>Паттерн: ClickHouse хранит “сырые” логи (миллиарды строк). Агрегаты и связи (User Graph) пересчитываются и заливаются в Графовую БД для быстрого lookup.<\/li>\n  <li>NebulaGraph** имеет Exchange (инструмент на основе Spark) для массовой заливки данных из Warehouse.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<hr \/>\n<h4>Итоговая рекомендация<\/h4>\n<p>Учитывая, что вы хотите <b>Open Source<\/b> и вам нужен <b>технический задел (масштабирование)<\/b> для AdTech:<\/p>\n<h5>🏆 Выбор №1: NebulaGraph<\/h5>\n<p>Это наиболее близкий аналог “ClickHouse в мире графов”.<\/p>\n<ul>\n<li>Почему:** Он создан для хранения миллиардов вершин (пользователей\/устройств) и работы в кластере. У него shared-nothing архитектура, которая необходима для роста. Язык nGQL будет понятен вашим аналитикам, знающим SQL (ClickHouse\/Trino).<\/li>\n<li>Для AdTech:** Идеально решает проблемы *Identity Resolution* (склеивание cookie, device_id, user_id и других атрибутов в единый граф) на больших объемах.<\/li>\n<\/ul>\n<h5>🥈 Выбор №2: Memgraph<\/h5>\n<p>Если ваши графы помещаются в память (сотни миллионов узлов, но не десятки миллиардов) и критична задержка (latency) менее 10 мс для *real-time* принятия решений.<\/p>\n<ul>\n<li>Почему:** Он безумно быстр. Он совместим с Cypher (легко нанимать людей или переезжать с Neo4j). Написан на C++, очень эффективен.<\/li>\n<li>Интеграция:** Идеально, если вы планируете стримить данные из Kafka, обновлять граф и сразу выдавать сегменты.<\/li>\n<\/ul>\n<h5>🥉 Выбор №3: Apache AGE (или ArangoDB)<\/h5>\n<p>Только если объем графа невелик, и вы хотите минимизировать зоопарк технологий, оставаясь в рамках “почти SQL” решений. Но для серьезного AdTech они не рекомендуется как *основное* хранилище графа пользователей.<\/p>\n<p><b>Совет:<\/b> Начните пилот (PoC) с <b>NebulaGraph<\/b>. Попробуйте загрузить туда выгрузку из ClickHouse и сравнить скорость выполнения запросов “найти всех пользователей, связанных через устройство X на глубину 3 шага” с тем, как это делается сейчас (вероятно, через JOINs в реляционке или CH). Если сложность эксплуатации Nebula покажется высокой, можно посмотреть в сторону <b>Memgraph<\/b> как более легкой альтернативы и применять их не на одном большом графе например, а на нескольких малых в реальном времени, а готовые расчеты уже хранить в привычных местах.<\/p>\n<p><b>Еще можно почитать:<\/b><\/p>\n<ul>\n<li><a href=\"https:\/\/bigdataschool.ru\/blog\/memgraph-vs-neo4j\/\">Сравнение Memgraph и Neo4j bigdataschool.ru<\/a><\/li>\n<li><a href=\"https:\/\/bigdataschool.ru\/blog\/neo4j-vs-tigergraph-what-to-choose.html\">Сравнение Neo4j и TigerGraph (для понимания коммерческого рынка bigdataschool.ru<\/a><\/li>\n<li><a href=\"https:\/\/wiki.merionet.ru\/articles\/10-lucsix-resenii-dlia-raboty-s-grafovymi-bazami-dannyx\">Обзор графовых БД wiki.merionet.ru<\/a><\/li>\n<\/ul>\n<p>Вот еще мысль и про языки немного. Если проект большой с единым графом для разных нужд, то NebulaGraph выглядит лучшим решением, но архитектурно можно выбрать много средних и малых графов. Для второго подхода хорошо Memgraph с его языком Cypher<\/p>\n<hr \/>\n<h4>1. Семейство Cypher (OpenCypher \/ ISO GQL)<\/h4>\n<p><b>Базы:<\/b> *Neo4j, Memgraph, FalkorDB, Apache AGE.*<\/p>\n<p>Cypher — это «SQL для графов». Это декларативный язык, использующий ASCII-арт для визуализации связей в коде (например, `(User)-[:CLICKS]->(Ad)`).<\/p>\n<ul>\n<li><b>Функциональность:<\/b> Очень богатая. Поддерживает сложные паттерны (Pattern Matching), агрегации, пути переменной длины. В апреле 2024 года ISO утвердила стандарт <b>GQL<\/b> (Graph Query Language), который во многом основан на Cypher.<\/li>\n<li><b>Плюсы:<\/b>\n<ul>\n  <li><b>Интуитивность:<\/b> Код читается как предложение на английском. Самая низкая кривая входа.<\/li>\n  <li><b>Экосистема:<\/b> Стандарт де-факто. Если вы знаете Cypher, вы можете переключаться между Neo4j, Memgraph и AGE без переобучения.<\/li>\n  <li><b>Выразительность:<\/b> Идеален для глубокой аналитики и поиска сложных паттернов (Fraud Detection).<\/li>\n<\/ul>\n<\/li>\n<li><b>Минусы:<\/b>\n<ul>\n  <li>Изначально создавался для одноузловых систем. В распределенных системах (шардинг) некоторые конструкции Cypher могут быть сложны для оптимизации движком.<\/li>\n<\/ul>\n<\/li>\n<li><b>Оценка для стека:<\/b>\n<ul>\n  <li><b>Memgraph\/Neo4j:<\/b> Работает идеально.<\/li>\n  <li><b>Apache AGE:<\/b> Cypher оборачивается внутри SQL запросов Postgres, что немного громоздко, но функционально.<\/li>\n  <li><b>FalkorDB:<\/b> Реализует подмножество Cypher, очень быстро благодаря Redis, но функционал беднее, чем у Neo4j.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>2. Семейство Gremlin (Apache TinkerPop)<\/h4>\n<p><b>Базы:<\/b> *JanusGraph, HugeGraph, OrientDB (частично), Azure CosmosDB.*<\/p>\n<p>Gremlin — это императивный язык обхода графа (Traversals). Вы пишете не «что найти» (как в SQL\/Cypher), а «куда идти» шаг за шагом.<\/p>\n<ul>\n<li><b>Функциональность:<\/b> Тьюринговская полнота. Можно написать алгоритм любой сложности прямо внутри запроса. Это скорее язык программирования потоков данных, чем язык запросов.<\/li>\n<li><b>Плюсы:<\/b>\n<ul>\n  <li><b>Контроль:<\/b> Вы точно указываете базе, как обходить граф. Это важно для сверхбольших графов (как в JanusGraph\/HugeGraph), где неверный план запроса может “положить” кластер.<\/li>\n  <li><b>Абстракция:<\/b> Работает поверх любой БД, поддерживающей TinkerPop.<\/li>\n<\/ul>\n<\/li>\n<li><b>Минусы:<\/b>\n<ul>\n  <li><b>Сложность:<\/b> Кривая обучения очень крутая. Код получается вербозным и сложным для отладки («write once, read never»).<\/li>\n  <li><b>Устаревание:<\/b> С появлением стандарта ISO GQL популярность Gremlin падает. Для новых проектов в 2025 году его выбирают редко, если только не привязаны к JanusGraph.<\/li>\n<\/ul>\n<\/li>\n<li><b>Пример AdTech:<\/b> «Найти всех пользователей, кликнувших на этот баннер» на Gremlin будет длинной цепочкой вызовов методов (`g.V().has(‘Banner’...).out(‘CLICKS’)...`).<\/li>\n<\/ul>\n<h4>3. nGQL (NebulaGraph Query Language)<\/h4>\n<p><b>Базы:<\/b> *NebulaGraph.*<\/p>\n<p>Собственный язык Nebula, который синтаксически мимикрирует под SQL, но логически работает с графами.<\/p>\n<ul>\n<li><b>Функциональность:<\/b> Заточена под распределенный Massive Parallel Processing (MPP).<\/li>\n<li><b>Плюсы:<\/b>\n<ul>\n  <li><b>SQL-подход:<\/b> Разработчикам, привыкшим к MySQL\/ClickHouse, синтаксис `GO FROM ... OVER ...` будет понятнее, чем Gremlin.<\/li>\n  <li><b>Скорость:<\/b> Спроектирован так, чтобы не позволять писать «плохие» запросы, которые убивают распределенный кластер. Вынуждает думать о том, где лежат данные (VID).<\/li>\n  <li><b>Пайпы:<\/b> Удобный синтаксис передачи результата одного шага в другой через `|` (как в Bash).<\/li>\n<\/ul>\n<\/li>\n<li><b>Минусы:<\/b>\n<ul>\n  <li><b>Vendor Lock-in:<\/b> Это не стандарт. Переехать с Nebula на другую базу потребует переписывания всех запросов.<\/li>\n  <li>Не поддерживает полную гибкость Pattern Matching, как Cypher (хотя добавили поддержку `MATCH`, она менее производительна, чем нативный `GO`).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>4. DQL (ранее GraphQL+-)<\/h4>\n<p><b>Базы:<\/b> *Dgraph.*<\/p>\n<p>Это модифицированный GraphQL.<\/p>\n<ul>\n<li><b>Функциональность:<\/b> Идеальна для API. Вы запрашиваете данные в формате JSON-дерева, и база возвращает JSON.<\/li>\n<li><b>Плюсы:<\/b>\n<ul>\n  <li><b>Frontend-first:<\/b> Фронтендерам не нужен бэкенд-прослойка, они могут (теоретически) ходить в базу почти напрямую.<\/li>\n  <li><b>Работа с атрибутами:<\/b> Поскольку Dgraph — это по сути распределенный Key-Value, DQL очень быстро достает атрибуты нод.<\/li>\n<\/ul>\n<\/li>\n<li><b>Минусы:<\/b>\n<ul>\n  <li><b>Слабая аналитика:<\/b> Графовые алгоритмы и сложные обходы (traversals) на DQL писать сложнее и менее эффективно, чем на Cypher\/nGQL. Это язык выборки данных, а не язык аналитики графов.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>5. AQL (ArangoDB Query Language)<\/h4>\n<p><b>Базы:<\/b> *ArangoDB.*<\/p>\n<p>Гибридный язык, объединяющий возможности SQL (JOINs), работы с JSON (как в Mongo) и графовых обходов.<\/p>\n<ul>\n<li><b>Функциональность:<\/b> Одна из самых мощных среди “универсалов”. Позволяет в одном запросе сделать JOIN трех коллекций, отфильтровать JSON и пройтись по графу друзей.<\/li>\n<li><b>Плюсы:<\/b> Гибкость.<\/li>\n<li><b>Минусы:<\/b> Синтаксис `FOR u IN users FILTER ...` специфичен и многословен. Для чистых графовых задач (deep hopping) он медленнее нативных решений [ArangoDB vs Native Graph].<\/li>\n<\/ul>\n<h4>6. Другие \/ Устаревающие<\/h4>\n<ul>\n<li><b>OrientDB (SQL-extended):<\/b> Пытались расширить SQL для графов. Сейчас проект стагнирует, язык считается тупиковой ветвью эволюции по сравнению с Cypher\/GQL.<\/li>\n<li><b>SQL Graph (MS SQL \/ PG SQL):<\/b> В [статье про SQL Server](<a href=\"https:\/\/learn.microsoft.com\/ru-ru\/sql\/relational-databases\/graphs\/sql-graph-sample?view=sql-server-ver17)\">https:\/\/learn.microsoft.com\/ru-ru\/sql\/relational-databases\/graphs\/sql-graph-sample?view=sql-server-ver17)<\/a> показан синтаксис `MATCH`, который Microsoft внедрила в T-SQL. Это попытка “догнать” Cypher, оставаясь в рамках реляционной модели. Удобно, если вы намертво привязаны к MS SQL, но неудобно для сложной аналитики.<\/li>\n<li><b>Cayley (Gizmo\/MQL):<\/b> Очень нишевый язык на базе Go или JS. Для AdTech продакшена слишком экзотичен.<\/li>\n<\/ul>\n<hr \/>\n<h4>Сводная таблица сравнения<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\">Язык<\/td>\n<td style=\"text-align: center\">Базы данных<\/td>\n<td style=\"text-align: center\">Порог входа<\/td>\n<td style=\"text-align: center\">Для AdTech\/High-load<\/td>\n<td style=\"text-align: center\">Стандартность (2025)<\/td>\n<td style=\"text-align: center\">Примечание<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>nGQL<\/b><\/td>\n<td style=\"text-align: center\"><b>NebulaGraph<\/b><\/td>\n<td style=\"text-align: center\">Средний<\/td>\n<td style=\"text-align: center\"><b>Идеально<\/b> (Tencent scale)<\/td>\n<td style=\"text-align: center\">Низкая (Vendor specific)<\/td>\n<td style=\"text-align: center\">Топ для сотен млрд связей и кластерной архитектуры.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Cypher<\/b><\/td>\n<td style=\"text-align: center\"><b>Memgraph<\/b>, Neo4j, AGE<\/td>\n<td style=\"text-align: center\"><b>Низкий<\/b><\/td>\n<td style=\"text-align: center\">Хорошо (Memgraph) \/ Средне (Neo4j)<\/td>\n<td style=\"text-align: center\"><b>Высокая<\/b> (основа ISO GQL)<\/td>\n<td style=\"text-align: center\">Самый удобный для аналитиков и Data Science.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>DQL<\/b><\/td>\n<td style=\"text-align: center\"><b>Dgraph<\/b><\/td>\n<td style=\"text-align: center\">Низкий (для Web-dev)<\/td>\n<td style=\"text-align: center\">Хорошо (для OLTP)<\/td>\n<td style=\"text-align: center\">Низкая<\/td>\n<td style=\"text-align: center\">Лучший выбор, если граф — это бэкенд для UI.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right\"><b>Gremlin<\/b><\/td>\n<td style=\"text-align: center\">JanusGraph, HugeGraph<\/td>\n<td style=\"text-align: center\">Высокий<\/td>\n<td style=\"text-align: center\">Отлично (если настроить)<\/td>\n<td style=\"text-align: center\">Падает (Legacy)<\/td>\n<td style=\"text-align: center\">Слишком сложен в поддержке, проигрывает современным языкам.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>AQL<\/b><\/td>\n<td style=\"text-align: center\">ArangoDB<\/td>\n<td style=\"text-align: center\">Средний<\/td>\n<td style=\"text-align: center\">Средне<\/td>\n<td style=\"text-align: center\">Низкая<\/td>\n<td style=\"text-align: center\">Хорош, если нужна “Document Store + Graph” в одном.<\/td>\n<\/tr>\n<\/table>\n<h4>Итоговая рекомендация<\/h4>\n<ol start=\"1\">\n<li><b>Если приоритет — производительность на масштабе (AdTech, сегментация 100M+ пользователей):<\/b>  <br \/>\nВам нужен <b>NebulaGraph<\/b> и его <b>nGQL<\/b>.<\/li>\n\n<ul>\n  <li>*Почему:* В AdTech сценариях (как у Meituan\/Tencent) критичны latency на “хопах” (hops). nGQL архитектурно заставляет писать запросы так, чтобы они эффективно параллелились. Он менее удобен, чем Cypher, но более предсказуем в нагрузке.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"2\">\n<li><b>Если приоритет — Real-time аналитика, ML-фичи и скорость разработки:<\/b>  <br \/>\nВам нужен <b>Memgraph<\/b> на <b>Cypher<\/b>.<\/li>\n\n<ul>\n  <li>*Почему:* Вы получаете совместимость с самой популярной экосистемой (Neo4j), стандартный язык Cypher (легко найти специалистов) и скорость C++ in-memory движка.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<ol start=\"3\">\n<li><b>Если приоритет — дешевое горизонтальное масштабирование “для бедных” (в хорошем смысле):<\/b>  <br \/>\nВам нужен <b>Dgraph<\/b> (DQL) или <b>NebulaGraph<\/b>.<\/li>\n\n<ul>\n  <li>У <b>Dgraph<\/b> отличный шардинг из коробки и DQL закрывает 90% задач продуктовой разработки, но может буксовать на тяжелой аналитике.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p><b>От чего стоит отказаться:<\/b><\/p>\n<ul>\n<li><b>Neo4j Community:<\/b> Язык Cypher прекрасен, но ограничения лицензии (отсутствие кластера) убьют проект на росте.<\/li>\n<li><b>JanusGraph\/HugeGraph (Gremlin):<\/b> В 2025 году начинать проект на Gremlin — это создавать себе технический долг, так как индустрия движется в сторону ISO GQL (Cypher Style).<\/li>\n<li><b>Apache AGE:<\/b> Пока слишком сыро для High-load, проблемы с горизонтальным масштабированием Postgres никуда не деваются.<\/li>\n<\/ul>\n",
            "date_published": "2025-12-14T14:24:45+03:00",
            "date_modified": "2025-12-18T23:42:57+03:00",
            "tags": [
                "Data",
                "Data Engineer",
                "Database",
                "Graph"
            ],
            "_date_published_rfc2822": "Sun, 14 Dec 2025 14:24:45 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "305",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "302",
            "url": "https:\/\/gavrilov.info\/all\/obzor-pg-clickhouse-kak-obedinit-mosch-clickhouse-i-udobstvo-pos\/",
            "title": "Обзор pg_clickhouse: Как объединить мощь ClickHouse и удобство PostgreSQL",
            "content_html": "<p>Недавно компания ClickHouse представила новый инструмент — расширение <b>pg_clickhouse<\/b>. Это событие стало ответом на одну из самых частых болей разработчиков: сложность миграции аналитических запросов из классических реляционных баз данных в колоночные аналитические СУБД.<\/p>\n<p>Оригинал статьи: <a href=\"https:\/\/clickhouse.com\/blog\/introducing-pg_clickhouse\">A Postgres extension for querying ClickHouse<\/a><\/p>\n<p>или берем сразу тут: <a href=\"https:\/\/github.com\/ClickHouse\/pg_clickhouse\/releases\">https:\/\/github.com\/ClickHouse\/pg_clickhouse\/releases<\/a><\/p>\n<p>В этой статье мы разберем, что представляет собой этот инструмент, в чем его фундаментальный смысл для архитектуры приложений и куда проект хочет двигаться дальше.<\/p>\n<h3>Проблема: Данные переехали, а запросы остались<\/h3>\n<p>Типичный сценарий роста стартапа выглядит так: приложение строится на PostgreSQL. В какой-то момент данных (логов, метрик, транзакций) становится так много, что аналитические отчеты начинают тормозить. Обычные реплики для чтения (read replicas) перестают спасать.<\/p>\n<p>Команда принимает решение внедрить ClickHouse. Перенос данных сейчас решается просто (например, с помощью ClickPipes), но возникает другая проблема:<br \/>\n<b>Как быть с тысячами строк SQL-кода в ORM, дашбордах и скриптах, которые написаны под синтаксис Postgres?<\/b><\/p>\n<p>Переписывание всей логики приложения под диалект ClickHouse — это месяцы работы и риск новых багов. Именно эту проблему решает `pg_clickhouse`.<\/p>\n<h3>Что такое pg_clickhouse?<\/h3>\n<p><b>pg_clickhouse<\/b> — это расширение для PostgreSQL (Foreign Data Wrapper — FDW), которое позволяет создавать в Postgres «внешние таблицы», фактически ссылающиеся на таблицы в ClickHouse.<\/p>\n<p><b>Суть технологии:<\/b> Вы пишете запросы на привычном SQL диалекте PostgreSQL, обращаясь к этим таблицам. Расширение на лету транслирует запрос в диалект ClickHouse, отправляет его на исполнение в аналитическую базу и возвращает результат обратно в Postgres.<\/p>\n<p>Для приложения это выглядит прозрачно: таблицы ClickHouse могут находиться просто в отдельной схеме (schema). Достаточно изменить путь поиска (`search_path`), и старые запросы начнут работать с данными, лежащими в ClickHouse.<\/p>\n<h3>В чем «соль»: Технология Pushdown<\/h3>\n<p>Главная ценность и сложность такого расширения заключается не просто в соединении двух баз, а в эффективности этого соединения. Этот механизм называется <b>Pushdown<\/b> (спуск или делегирование вычислений).<\/p>\n<p>Если вы делаете запрос `SELECT sum(price) FROM orders`, есть два пути его выполнения:<\/p>\n<ol start=\"1\">\n<li><b>Плохой путь:<\/b> Postgres выкачивает *все* миллионы строк из ClickHouse и сам считает сумму. Это уничтожает весь смысл аналитической базы.<\/li>\n<li><b>Путь pg_clickhouse:<\/b> Расширение понимает, что это агрегация, и отправляет в ClickHouse команду «посчитай сумму». Обратно по сети возвращается только одна цифра.<\/li>\n<\/ol>\n<h4>Умная трансляция функций<\/h4>\n<p>Авторы `pg_clickhouse` пошли дальше простой трансляции. Они научили расширение переводить специфические функции Postgres в аналоги ClickHouse, даже если синтаксис кардинально отличается.<\/p>\n<p>*Пример:*<br \/>\nВ Postgres есть функция для расчета медианы: `percentile_cont(0.5) WITHIN GROUP (ORDER BY price)`.<br \/>\nВ ClickHouse такой синтаксис не поддерживается.<br \/>\n`pg_clickhouse` автоматически переписывает это в нативную функцию ClickHouse: `quantile(0.5)(price)`.<\/p>\n<p>Также поддерживается трансляция конструкции `FILTER (WHERE ...)` в специфичные для ClickHouse комбинаторы `-If` (например, `sumIf`).<\/p>\n<h4>Ускорение подзапросов (Semi-Join)<\/h4>\n<p>В версии 0.1.0 была реализована поддержка <b>SEMI JOIN Pushdown<\/b>. Это критически важно для запросов с конструкцией `WHERE ... IN (SELECT ...)` или `EXISTS`. Тесты на бенчмарке TPC-H показали, что благодаря этому время выполнения сложных запросов сократилось с нескольких секунд (или даже минут) до миллисекунд, так как фильтрация теперь происходит на стороне ClickHouse.<\/p>\n<h3>Планы развития (Roadmap)<\/h3>\n<p>Проект находится в стадии активной разработки (версия 0.1.0), и команда ClickHouse нацелена на полное покрытие аналитических сценариев.<\/p>\n<p><b>Ключевые пункты плана:<\/b><\/p>\n<ol start=\"1\">\n<li><b>Полное покрытие TPC-H и ClickBench:<\/b> Оптимизация планировщика, чтобы все стандартные аналитические бенчмарки выполнялись с максимальным pushdown-ом.<\/li>\n<li><b>Расширенная поддержка функций:<\/b> Трансляция *всех* агрегатных и обычных функций PostgreSQL в их эквиваленты в ClickHouse.<\/li>\n<li><b>DML операции:<\/b> Поддержка легковесных удалений (`DELETE`) и обновлений (`UPDATE`), а также пакетной вставки данных через `COPY`.<\/li>\n<li><b>Управление настройками:<\/b> Возможность передавать настройки ClickHouse (settings) через команды создания пользователей или серверов в Postgres.<\/li>\n<li><b>Passthrough-режим:<\/b> Возможность отправить произвольный SQL-запрос (на диалекте ClickHouse) и получить результат в виде таблицы, обходя парсер Postgres.<\/li>\n<\/ol>\n<h3>Заключение<\/h3>\n<p>`pg_clickhouse` — это попытка построить «лучшее из двух миров»: взять скорость колоночной СУБД и объединить её с богатой экосистемой и инструментарием PostgreSQL. Это позволяет разработчикам плавно мигрировать нагрузку, не переписывая приложение с нуля, и оставляет Postgres в качестве единой точки входа для данных.<\/p>\n",
            "date_published": "2025-12-12T23:27:54+03:00",
            "date_modified": "2025-12-12T23:32:31+03:00",
            "tags": [
                "Data",
                "Data Engineer",
                "Database",
                "Dev"
            ],
            "_date_published_rfc2822": "Fri, 12 Dec 2025 23:27:54 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "302",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "286",
            "url": "https:\/\/gavrilov.info\/all\/bitva-novyh-arhitektur-sravnivaem-arc-gigapi-i-ducklake\/",
            "title": "Битва Новых Архитектур: Сравниваем Arc, GigAPI и DuckLake",
            "content_html": "<p>В мире данных происходит тихая революция. На смену тяжеловесным и дорогим OLAP-системам приходят легковесные, но мощные решения, построенные на идеологии Lakehouse. Они обещают гибкость озер данных и надежность хранилищ без лишней сложности и затрат.<\/p>\n<p>Можно еще почитать тут: <a href=\"https:\/\/habr.com\/ru\/articles\/955536\/\">https:\/\/habr.com\/ru\/articles\/955536\/<\/a><\/p>\n<p>В этой статье мы сравним два таких проекта для работы с временными рядами — <b>Arc<\/b> и <b>GigAPI<\/b>. А также разберемся, какое место в этой экосистеме занимает <b>DuckLake<\/b> — технология, которую пока еще могут путать с Arc.<\/p>\n<h4>🆚 Arc vs. GigAPI: Сравнительная таблица<\/h4>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-220.png\" width=\"1024\" height=\"1024\" alt=\"\" \/>\n<\/div>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/image-221.png\" width=\"769\" height=\"232\" alt=\"\" \/>\n<\/div>\n<p>Это прямые конкуренты, решающие задачу хранения и анализа временных рядов, но с разной философией.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\"><b>Параметр<\/b><\/td>\n<td style=\"text-align: center\"><b>Arc<\/b><\/td>\n<td style=\"text-align: center\"><b>GigAPI<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Основной подход<\/b><\/td>\n<td style=\"text-align: center\">Автономная Time-Series база данных «в одном файле» на базе DuckDB.<\/td>\n<td style=\"text-align: center\">Унифицированный слой для запросов и управления жизненным циклом данных (Lakehouse).<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Стадия развития<\/b><\/td>\n<td style=\"text-align: center\">Альфа, <b>не для продакшена<\/b>.<\/td>\n<td style=\"text-align: center\">Открытая бета, активные релизы.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Архитектура<\/b><\/td>\n<td style=\"text-align: center\">Монолитный бинарный файл, простой запуск.<\/td>\n<td style=\"text-align: center\">Набор микросервисов (`aio`, `readonly`, `writeonly`, `compaction`).<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: right\"><b>Производительность (ingest)<\/b><\/td>\n<td style=\"text-align: center\">Заявлено до <b>~1.89 млн записей\/сек<\/b> (нативным протоколом).<\/td>\n<td style=\"text-align: center\">Субсекундные аналитические запросы. Производительность ingest зависит от бэкенда.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Протоколы ввода данных<\/b><\/td>\n<td style=\"text-align: center\">MessagePack (рекомендуемый), InfluxDB Line Protocol <a href=\"https:\/\/github.com\/Basekick-Labs\/arc\">arc<\/a>.<\/td>\n<td style=\"text-align: center\">InfluxDB Line Protocol, Native JSON. Планируется FlightSQL <a href=\"https:\/\/github.com\/gigapi\/gigapi\">gigapi<\/a>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Управление данными<\/b><\/td>\n<td style=\"text-align: center\">ACID-транзакции, Time Travel, Schema Evolution (унаследовано от Lakehouse-архитектуры).<\/td>\n<td style=\"text-align: center\"><b>Автоматическая компакция<\/b>, <b>перемещение данных (tiering)<\/b> между FS и S3, <b>удаление по TTL<\/b>.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>Лицензия<\/b><\/td>\n<td style=\"text-align: center\"><b>AGPL-3.0<\/b> (важное ограничение для коммерческого использования).<\/td>\n<td style=\"text-align: center\"><b>MIT<\/b> (максимально разрешительная).<\/td>\n<\/tr>\n<\/table>\n<h4>Ключевые отличия в подходах: Arc и GigAPI<\/h4>\n<h5>Arc: Максимальная простота и скорость для старта<\/h5>\n<p><b>Arc<\/b> <a href=\"https:\/\/github.com\/Basekick-Labs\/arc\">arc<\/a> — это полноценная база данных временных рядов, которую можно скачать и запустить одной командой.<\/p>\n<ul>\n<li><b>Идеология:<\/b> “Батарейки в комплекте”. Arc предоставляет готовое решение с ACID-транзакциями, time travel и эволюцией схемы “из коробки”. Он спроектирован для максимальной простоты развертывания и сверхбыстрого приема данных.<\/li>\n<li><b>Сценарий использования:<\/b> Идеален для R&D, прототипирования и внутренних проектов, где нужна высокая производительность без сложной настройки.<\/li>\n<li><b>Ключевой компромисс:<\/b> Лицензия AGPL-3.0 требует, чтобы любое сетевое приложение, использующее Arc, также открывало свой исходный код. Это делает его неприменимым для многих коммерческих продуктов.<\/li>\n<\/ul>\n<h5>GigAPI: Операционная мощь для продакшена<\/h5>\n<p><b>GigAPI<\/b> <a href=\"https:\/\/github.com\/gigapi\/gigapi\">gigapi<\/a> — это не база данных, а скорее <b>интеллектуальный операционный слой<\/b> или шлюз, который работает поверх ваших данных.<\/p>\n<ul>\n<li><b>Идеология:<\/b> “Оркестратор и оптимизатор”. GigAPI фокусируется на промышленной эксплуатации и автоматизации рутинных задач. Его микросервисы (`merge`, `move`, `drop`) следят за здоровьем хранилища: уплотняют мелкие файлы, перемещают старые данные в дешевое S3-хранилище и удаляют их по истечении срока жизни (TTL).<\/li>\n<li><b>Сценарий использования:<\/b> Построение зрелого, экономически эффективного и надежного пайплайна для временных рядов в production-среде. Разрешительная лицензия MIT делает его отличным выбором для бизнеса.<\/li>\n<li><b>Ключевое преимущество:<\/b> Архитектурная гибкость и фокус на снижении эксплуатационных расходов (OpEx).<\/li>\n<\/ul>\n<h4>А где же DuckLake?<\/h4>\n<p><b>DuckLake<\/b> — это не база данных, а <b>открытый табличный формат<\/b> и <b>расширение для DuckDB<\/b> <a href=\"https:\/\/github.com\/duckdb\/ducklake\">ducklake<\/a>. Его цель — упростить создание Lakehouse, используя SQL в качестве слоя метаданных <a href=\"https:\/\/duckdb.org\/2025\/05\/27\/ducklake.html\">ducklake blog<\/a>.<\/p>\n<p>Представьте, что у вас есть набор Parquet-файлов в S3. Чтобы работать с ними как с единой таблицей и иметь транзакции, традиционно нужен сложный компонент вроде Hive Metastore или Nessie. DuckLake предлагает более простой путь:<\/p>\n<blockquote>\n<p>Используйте обычную SQL-базу (например, DuckDB, SQLite или даже Postgres) для хранения всей метаинформации о файлах, версиях и схеме.<\/p>\n<\/blockquote>\n<p>Таким образом, DuckLake — это <b>фундаментальный строительный блок<\/b>, а не готовое приложение. Он конкурирует с Apache Iceberg и Delta Lake, предлагая более простую альтернативу. Недавние обновления даже добавили <b>совместимость с Iceberg<\/b>, что делает его еще более мощным инструментом <a href=\"https:\/\/ducklake.select\/2025\/09\/17\/ducklake-03\/\">ducklake.select<\/a>.<\/p>\n<h4>Сравнение с рынком: Альтернативы и выбор<\/h4>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: center\"><b>Система<\/b><\/td>\n<td style=\"text-align: center\"><b>Сильные стороны<\/b><\/td>\n<td style=\"text-align: center\"><b>Слабые стороны \/ Риски<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>InfluxDB 3.0<\/b><\/td>\n<td style=\"text-align: center\">Зрелая экосистема для временных рядов, Lakehouse архитектура “под капотом”.<\/td>\n<td style=\"text-align: center\">Стоимость для enterprise, привязка к своей экосистеме.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>QuestDB<\/b><\/td>\n<td style=\"text-align: center\">Высокая скорость вставок и SQL-запросов, простой опыт TSDB.<\/td>\n<td style=\"text-align: center\">Менее универсален для “озер” на S3, чем конкуренты.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>TimescaleDB<\/b><\/td>\n<td style=\"text-align: center\">Полная совместимость с экосистемой PostgreSQL.<\/td>\n<td style=\"text-align: center\">Привязанность к PostgreSQL и его модели масштабирования.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: center\"><b>ClickHouse<\/b><\/td>\n<td style=\"text-align: center\">Универсальный OLAP-движок, мощные возможности для временных рядов, горизонтальное масштабирование.<\/td>\n<td style=\"text-align: center\">Высокие эксплуатационные расходы, сложность настройки кластера.<\/td>\n<\/tr>\n<\/table>\n<h4>Когда что выбирать?<\/h4>\n<ul>\n<li><b>Выберите Arc<\/b>, если вам нужен <b>максимально быстрый старт<\/b> для прототипа или внутреннего проекта, вы не боитесь альфа-версии и вас полностью устраивает <b>лицензия AGPL-3.0<\/b>.<\/li>\n<\/ul>\n<ul>\n<li><b>Выберите GigAPI<\/b>, если вы строите <b>продакшн-систему<\/b>, вам важна <b>автоматизация рутинных задач<\/b> (compaction, tiering, TTL) и нужна <b>разрешительная лицензия MIT<\/b> для коммерческого использования.<\/li>\n<\/ul>\n<ul>\n<li><b>Используйте DuckLake<\/b>, если вы уже работаете с DuckDB и хотите построить <b>свой собственный, простой Lakehouse<\/b> на базе Parquet-файлов, избегая сложности стека Hadoop\/Spark.<\/li>\n<\/ul>\n<ul>\n<li><b>Обратитесь к ClickHouse\/Druid<\/b>, когда нужны <b>жесткие SLA, горизонтальное масштабирование<\/b> и высокий параллелизм для тысяч одновременных пользователей.<\/li>\n<\/ul>\n<ul>\n<li><b>Рассмотрите QuestDB\/Timescale<\/b>, если приоритетом является <b>предельно простой опыт работы с TSDB<\/b> или глубокая интеграция с экосистемой Postgres.<\/li>\n<\/ul>\n<h4>Заключение<\/h4>\n<p><b>Arc<\/b>, <b>GigAPI<\/b> и <b>DuckLake<\/b> — яркие представители тренда на прагматичные и экономичные решения для данных.<\/p>\n<ul>\n<li><b>Arc<\/b> — спринтер для быстрого старта.<\/li>\n<li><b>GigAPI<\/b> — марафонец для надежной работы в продакшене.<\/li>\n<li><b>DuckLake<\/b> — набор инструментов для архитектора, позволяющий построить легковесный и современный дом для данных.<\/li>\n<\/ul>\n<p>Их появление говорит о том, что рынку нужны не только монструозные системы, но и решения с оптимальным соотношением “простота\/стоимость\/функциональность”.<\/p>\n<p>Вот так выглядит:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-11-v-23.58.08.png\" width=\"2094\" height=\"1162\" alt=\"\" \/>\n<\/div>\n<pre class=\"e2-text-code\"><code class=\"\">services:\n  gigapi:\n    image: ghcr.io\/gigapi\/gigapi:latest\n    container_name: gigapi\n    hostname: gigapi\n    restart: unless-stopped\n    volumes:\n      - .\/data:\/data\n    ports:\n      - &quot;7971:7971&quot;\n      - &quot;8082:8082&quot;\n    environment:\n      - PORT=7971\n      - GIGAPI_ENABLED=true\n      - GIGAPI_MERGE_TIMEOUT_S=10\n      - GIGAPI_ROOT=\/data\n      - GIGAPI_LAYERS_0_NAME=default\n      - GIGAPI_LAYERS_0_TYPE=fs\n      - GIGAPI_LAYERS_0_URL=file:\/\/\/data\n      - GIGAPI_LAYERS_0_GLOBAL=false\n      - GIGAPI_LAYERS_0_TTL=12h\n      - GIGAPI_LAYERS_1_NAME=s3\n      - GIGAPI_LAYERS_1_TYPE=s3\n      - GIGAPI_LAYERS_1_URL=s3:\/\/gateway.XXXXX\/test\/gigapi\n      - GIGAPI_LAYERS_1_AUTH_KEY=XXXXX\n      - GIGAPI_LAYERS_1_AUTH_SECRET=XXXXX\n      - GIGAPI_LAYERS_1_GLOBAL=true\n      - GIGAPI_LAYERS_1_TTL=0<\/code><\/pre><p>А данные пишем так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">cat &lt;&lt;EOF | curl -X POST &quot;http:\/\/localhost:7971\/write?db=mydb&quot; --data-binary @\/dev\/stdin\nweather,location=us-midwest,season=summer temperature=82\nweather,location=us-east,season=summer temperature=123\nweather,location=us-west,season=summer temperature=111\nEOF<\/code><\/pre><p>Первый раз нужно отправить сообщение, что бы создалась база.<\/p>\n<p>файлики пишет, но че то пока не на s3, видимо надо дождаться как они переедут с кеша на s3<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-12-v-00.01.54.png\" width=\"924\" height=\"444\" alt=\"\" \/>\n<\/div>\n<p>Выше пример не сработал, точнее он работал, но не копировал данные на s3<\/p>\n<p>вот это рабочий вариант<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># docker-compose.yml\nversion: '3.8'\n\nservices:\n  gigapi:\n    build: . \n    container_name: gigapi\n    restart: unless-stopped\n    volumes:\n      - .\/gigapi_data:\/data\n    ports:\n      - &quot;7971:7971&quot;\n      - &quot;8082:8082&quot;\n    environment:\n      # --- Общие настройки GigAPI ---\n      - GIGAPI_ROOT=\/data \n      - HTTP_PORT=7971\n      - LOGLEVEL=info\n      - GIGAPI_UI=true\n\n      # --- Конфигурация Слоя 0: Локальный кэш на диске ---\n      - GIGAPI_LAYERS_0_NAME=local_cache\n      - GIGAPI_LAYERS_0_TYPE=fs\n      - GIGAPI_LAYERS_0_URL=file:\/\/\/data\/cache\n      - GIGAPI_LAYERS_0_GLOBAL=false\n      - GIGAPI_LAYERS_0_TTL=10m\n\n      # --- Конфигурация Слоя 1: Хранилище Storj S3 ---\n      - GIGAPI_LAYERS_1_NAME=storj_s3\n      - GIGAPI_LAYERS_1_TYPE=s3\n      - GIGAPI_LAYERS_1_URL=s3:\/\/gateway.storjshare.io\/test\/gigapi\/data?url-style=path\n      - GIGAPI_LAYERS_1_AUTH_KEY=XXXXXX\n      - GIGAPI_LAYERS_1_AUTH_SECRET=XXXXX\n      - GIGAPI_LAYERS_1_GLOBAL=true\n      - GIGAPI_LAYERS_1_TTL=0<\/code><\/pre><p>И пришлось серты обновить<\/p>\n<pre class=\"e2-text-code\"><code class=\"\"># Dockerfile\n\n# Берем за основу официальный образ gigapi\nFROM ghcr.io\/gigapi\/gigapi:latest\n\n# Переключаемся на пользователя root для установки пакетов\nUSER root\n\n# Обновляем список пакетов и устанавливаем корневые сертификаты.\n# Эта команда сначала пытается использовать 'apt-get' (для Debian\/Ubuntu).\n# Если эта команда завершается с ошибкой (оператор ||), то\n# выполняется вторая команда с 'apk' (для Alpine).\n# Это делает Dockerfile более универсальным.\nRUN if command -v apt-get &amp;&gt; \/dev\/null; then \\\n        apt-get update &amp;&amp; apt-get install -y --no-install-recommends ca-certificates &amp;&amp; apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*; \\\n    elif command -v apk &amp;&gt; \/dev\/null; then \\\n        apk add --no-cache ca-certificates; \\\n    else \\\n        echo &quot;Error: Neither apt-get nor apk found. Cannot install ca-certificates.&quot; &gt;&amp;2; \\\n        exit 1; \\\n    fi\n\n# Возвращаемся к стандартному пользователю (если он есть)\n# USER gigapi<\/code><\/pre><div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.34.22.png\" width=\"1492\" height=\"176\" alt=\"\" \/>\n<\/div>\n<p>Там кстати еще чатгпт апи можно вставить<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.37.35.png\" width=\"1588\" height=\"1216\" alt=\"\" \/>\n<\/div>\n<p>И дашборды есть еще<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.39.54.png\" width=\"1710\" height=\"642\" alt=\"\" \/>\n<\/div>\n<p>Еще про s3 подобные архитектуры:<br \/>\n<a href=\"https:\/\/gavrilov.info\/all\/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la\">https:\/\/gavrilov.info\/all\/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la<\/a><\/p>\n",
            "date_published": "2025-10-12T00:02:44+03:00",
            "date_modified": "2025-10-14T23:19:00+03:00",
            "tags": [
                "big data",
                "Data",
                "Database"
            ],
            "image": "https:\/\/gavrilov.info\/pictures\/image-220.png",
            "_date_published_rfc2822": "Sun, 12 Oct 2025 00:02:44 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "286",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/gavrilov.info\/pictures\/image-220.png",
                    "https:\/\/gavrilov.info\/pictures\/image-221.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-11-v-23.58.08.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-12-v-00.01.54.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.34.22.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.37.35.png",
                    "https:\/\/gavrilov.info\/pictures\/Snimok-ekrana-2025-10-13-v-22.39.54.png"
                ]
            }
        },
        {
            "id": "94",
            "url": "https:\/\/gavrilov.info\/all\/vybiraem-bazy-dannyh\/",
            "title": "Выбираем базы данных",
            "content_html": "<p>Статья с хабра про выбор баз данных<br \/>\n<a href=\"https:\/\/habr.com\/ru\/articles\/775574\/\">https:\/\/habr.com\/ru\/articles\/775574\/<\/a><\/p>\n",
            "date_published": "2023-12-10T22:19:55+03:00",
            "date_modified": "2023-12-10T22:19:52+03:00",
            "tags": [
                "Database"
            ],
            "_date_published_rfc2822": "Sun, 10 Dec 2023 22:19:55 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "94",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        }
    ],
    "_e2_version": 4171,
    "_e2_ua_string": "Aegea 11.4 (v4171e)"
}