Перейти к содержанию
Learning Platform
Глоссарий Troubleshooting
Урок 16.03 · 30 мин
Продвинутый
clickhouse-localpipelinestdinstdoutS3 table functionremote()ETLshell integration

clickhouse-local: продвинутые сценарии

clickhouse-local — одиночный бинарный файл с полным движком ClickHouse, не требующий запуска сервера. Базовое использование (установка, первые запросы) рассматривается в Модуле 00 урок 03. Этот урок фокусируется на продвинутых сценариях: pipeline обработке, shell-интеграции и ad-hoc ETL без сервера.

TIP

clickhouse-local поддерживает ВСЕ функции и форматы ClickHouse — включая S3 table function, Parquet, JSON, Avro, агрегатные функции и MergeTree на локальных файлах. Это полноценный ClickHouse, а не урезанный клиент.


Pipeline паттерны: stdin/stdout обработка

clickhouse-local интегрируется с Unix-пайплайнами через stdin и stdout. Это позволяет строить цепочки обработки данных без промежуточного хранения.

Конвертация форматов

# CSV -> Parquet: читаем CSV через stdin, выводим Parquet в файл
cat events.csv | clickhouse local \
    --query "SELECT * FROM table" \
    --input-format CSV \
    --output-format Parquet \
    > events.parquet

# Parquet -> JSON Lines: конвертация без потерь
clickhouse local \
    --query "SELECT * FROM file('events.parquet', Parquet)" \
    --format JSONEachRow \
    > events.jsonl

# JSON Lines -> фильтрованный CSV
clickhouse local \
    --query "SELECT user_id, event_type, toDate(event_time) AS date
             FROM table
             WHERE event_type = 'purchase'" \
    --input-format JSONEachRow \
    --format CSV \
    < events.jsonl > purchases.csv

Трансформация с агрегацией

# Агрегация большого CSV файла без загрузки в сервер
clickhouse local --query "
    SELECT
        toDate(event_time)   AS date,
        event_type,
        count()              AS total,
        uniq(user_id)        AS unique_users,
        sum(revenue)         AS total_revenue
    FROM file('events_*.csv', CSV, 'event_time DateTime, event_type String, user_id UInt64, revenue Float64')
    GROUP BY date, event_type
    ORDER BY date, total DESC
    FORMAT PrettyCompact
"

Shell-интеграция: аналитика из скриптов

clickhouse-local эффективен как инструмент командной строки в bash-скриптах. Полная поддержка ClickHouse SQL позволяет заменить awk/sed для обработки структурированных данных.

Анализ лог-файлов

#!/bin/bash
# Анализ nginx access.log: топ-10 IP по числу запросов за последний час

LOG_FILE="/var/log/nginx/access.log"
ONE_HOUR_AGO=$(date -d '1 hour ago' '+%d/%b/%Y:%H:%M:%S' 2>/dev/null || \
               date -v-1H '+%d/%b/%Y:%H:%M:%S')

clickhouse local --query "
    SELECT
        extractAll(line, '^(\\S+)')[1]    AS ip,
        count()                            AS requests
    FROM file('${LOG_FILE}', LineAsString, 'line String')
    WHERE positionCaseInsensitive(line, '${ONE_HOUR_AGO}') > 0
       OR line > '${ONE_HOUR_AGO}'
    GROUP BY ip
    ORDER BY requests DESC
    LIMIT 10
    FORMAT TabSeparated
"

Конвертация форматов в скрипте CI/CD

#!/bin/bash
# Конвертация дампа данных: JSON -> Parquet перед загрузкой в S3

INPUT_DIR="./export"
OUTPUT_DIR="./parquet"

mkdir -p "${OUTPUT_DIR}"

for json_file in "${INPUT_DIR}"/*.jsonl; do
    base=$(basename "${json_file}" .jsonl)
    output="${OUTPUT_DIR}/${base}.parquet"

    clickhouse local --query "
        SELECT *
        FROM file('${json_file}', JSONEachRow)
    " --format Parquet > "${output}"

    echo "Converted: ${json_file} -> ${output}"
done

Сравнение двух датасетов

# Проверка: все строки из source присутствуют в target
clickhouse local --query "
    SELECT count() AS missing_rows
    FROM file('source.csv', CSV, 'id UInt64, value String') AS s
    WHERE s.id NOT IN (
        SELECT id FROM file('target.csv', CSV, 'id UInt64, value String')
    )
    FORMAT PrettyCompact
"

Ad-hoc ETL: S3 и remote()

S3 table function без сервера

clickhouse-local поддерживает s3() table function — можно читать данные из S3 без запущенного ClickHouse сервера.

# Читаем Parquet файлы из S3, агрегируем и выводим в CSV
clickhouse local --query "
    SELECT
        toStartOfMonth(event_time) AS month,
        region,
        count()                   AS total_events,
        sum(revenue)              AS total_revenue
    FROM s3(
        'https://my-bucket.s3.amazonaws.com/events/2026/**/*.parquet',
        'ACCESS_KEY_ID',
        'SECRET_ACCESS_KEY',
        Parquet
    )
    GROUP BY month, region
    ORDER BY month, total_revenue DESC
    FORMAT CSV
" > monthly_report.csv
# Фильтрация и конвертация больших файлов из S3 -> локальный Parquet
clickhouse local --query "
    SELECT user_id, event_type, event_time
    FROM s3(
        'https://my-bucket.s3.amazonaws.com/raw/events.csv.gz',
        'ACCESS_KEY_ID',
        'SECRET_ACCESS_KEY',
        'CSVWithNames'
    )
    WHERE event_time >= toDateTime('2026-01-01 00:00:00')
      AND event_type IN ('purchase', 'refund')
" --format Parquet > filtered_events.parquet

remote() — запросы к работающему серверу

remote() table function позволяет clickhouse-local запрашивать данные из работающего ClickHouse сервера. Полезно для ad-hoc анализа production данных без постоянного подключения.

# Запрос к production серверу из clickhouse-local
clickhouse local --query "
    SELECT
        database,
        table,
        formatReadableSize(sum(bytes_on_disk)) AS total_size,
        sum(rows)                              AS total_rows,
        count()                                AS parts_count
    FROM remote('prod-clickhouse:9000', system, parts, 'default', 'password')
    WHERE active = 1
    GROUP BY database, table
    ORDER BY sum(bytes_on_disk) DESC
    LIMIT 20
    FORMAT PrettyCompact
"
# Экспорт данных с production сервера в локальный Parquet
clickhouse local --query "
    SELECT *
    FROM remote('prod-clickhouse:9000', analytics, user_events, 'reader', 'readonly_pass')
    WHERE event_time >= today() - 7
" --format Parquet > last_7_days.parquet

Характеристики производительности

clickhouse-local запускает полноценный ClickHouse движок в рамках одного процесса. Это означает:

Доступны все возможности ClickHouse:

  • Параллельное чтение с несколькими потоками (--max-threads)
  • Полный набор агрегатных функций, включая approximate (uniqHLL12, quantileTDigest)
  • MergeTree файлы на локальной файловой системе (с поддержкой merge при повторных запросах)
  • Словари, Materialized Views (в рамках сессии)

Настройки производительности:

# Увеличить число потоков для обработки больших файлов
clickhouse local \
    --max-threads 8 \
    --query "SELECT count() FROM file('huge.parquet', Parquet)"

# Ограничить использование памяти
clickhouse local \
    --max-memory-usage 4000000000 \
    --query "SELECT ... FROM file('*.csv', CSV) GROUP BY ..."

# Использовать MergeTree для повторных запросов к одним данным
clickhouse local \
    --path /tmp/ch-local-data \
    --query "
        CREATE TABLE events ENGINE = MergeTree ORDER BY id
        AS SELECT * FROM file('events.csv', CSV);

        SELECT count(), uniq(user_id) FROM events;
        SELECT event_type, count() FROM events GROUP BY event_type;
    "

Ограничения по сравнению с сервером:

  • Нет репликации и распределённых запросов
  • Нет background merges (данные в MergeTree не мёрджятся автоматически)
  • Нет HTTP API — только CLI интерфейс
  • Нет постоянных Materialized Views между сессиями

Ключевые выводы

  1. Полный движок ClickHouse без сервера. clickhouse-local поддерживает все функции, форматы и table functions — включая S3, remote(), агрегации и MergeTree.
  2. Pipeline через stdin/stdout. Нативная интеграция с Unix-пайплайнами: cat file.csv | clickhouse local --query "..." > output.parquet.
  3. S3 без сервера. s3() table function работает в clickhouse-local — можно читать и трансформировать данные из S3 без запущенного ClickHouse сервера.
  4. remote() для ad-hoc анализа production. Запросы к работающему серверу из clickhouse-local: экспорт данных, одноразовые отчёты без постоянного клиента.
  5. Параллельная обработка и MergeTree доступны. --max-threads для параллелизма, --path для персистентного MergeTree между запросами в рамках сессии.
ELT без инфраструктуры: local transformations и serverless ETL Trino: чтение CSV, Parquet и JSON напрямую без ETL

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7