Больше о CHYT 2.16

Рассказываем об изменениях в новой версии CHYT и CHYT HTTP‑Proxy

TL;DR. Что мы сделали:

  • поддержали Query Cache;

  • добавили оптимизацию optimize_read_in_order;

  • внедрили новый алгоритм PREWHERE для оптимизации при конвертации данных;

  • подключили экспорт системных таблиц с логами в Cypress;

  • поддержали широкие типы дат bool, date32, datetime64, timestamp64, interval64, типы данных JSON и Map, а также JSON_*‑функции в ClickHouse®;

  • добавили возможность задавать YTsaurus директории как database;

  • обновили прокси и сделали HTTP‑интерфейс более похожим на ClickHouse.

А теперь — подробнее о нововведениях.

Поддержка Query Cache

В ClickHouse есть механизм кеширования результатов запроса. Он помогает избежать многократного выполнения одного и того же запроса в течение заданного параметром query_cache_ttl времени. Настройки параметров кеширования идентичны тем, что используются в стандартном ClickHouse.

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

Такой подход обеспечит большую устойчивость системы в случае неполадки и позволит равномернее распределить нагрузку внутри клики. Пользователь сможет самостоятельно выбирать размер группы исходя из своего сценария использования: от 1 до размера клики. Настройка задаётся параметром query_sticky_group_size через веб‑интерфейс CHYT в блоке Advanced.

Распределение запросов до версии 2.16
Распределение запросов для версии 2.16 и выше. Sticky group size = 1
Распределение запросов для версии 2.16 и выше. Sticky group size = 2

Оптимизация производительности

Оптимизация optimize_read_in_order

В рамках CHYT реализована оптимизация optimize_read_in_order, которая уже существует в ClickHouse. Она позволяет читать существенно меньше данных. Оптимизация сработает, если взять N строчек через LIMIT, а при этом ORDER BY попадает по префиксу ключа сортировки. Оптимизация будет читать данные синхронно в одном потоке, а результат не нужно будет дополнительно сортировать: строки из хранилища будут получены в отсортированном порядке.

В качестве примера можно взять датасет ClickBench и выполнить запрос:

SELECT
    *
FROM `//home/hits`
WHERE JavaEnable = 1
ORDER BY CounterID 
LIMIT 10 
SETTINGS chyt.execution.enable_optimize_read_in_order=0

Статистика выполнения запроса при выключенной оптимизации:

"statistics":
  {
    "elapsed": 16.275991788,
    "rows_read": 67121367,
    "bytes_read": 55649417111
  }

А теперь давайте включим chyt.execution.enable_optimize_read_in_order=1:

"statistics":
  {
    "elapsed": 1.799395613,
    "rows_read": 142941,
    "bytes_read": 130585788
  }

Скорость выросла на порядок. Вместо 67 млн строчек мы прочитали только около 143 тыс.

Новый алгоритм работы PREWHERE для оптимизации конвертации данных

Значительную долю CPU в кликах потребляет процесс конвертации данных из формата YT в формат ClickHouse. В то же время условие WHERE может отфильтровывать большое количество данных. Получается, что работа по конвертации проделывается зря.

Для оптимизации накладных расходов на конвертацию мы реализовали новый механизм PREWHERE. Он работает на уровне конвертации: сначала конвертируются только те колонки, которые участвуют в условии PREWHERE, на этих колонках выполняется условие PREWHERE. А конвертация остальных колонок с тяжёлыми для конвертации типами — массивами, структурами, длинными строками — происходит только для подходящих по условию строк.

Алгоритм PREWHERE не читает колонки дважды и не замедляет запрос в худшем случае.

По умолчанию алгоритм PREWHERE переключён на новый. Значение опции optimize_move_to_prewhere изменено на 1, чтобы оптимизация работала без явного указания условия PREWHERE. Включить старый алгоритм PREWHERE можно с помощью опции chyt.prewhere.prefilter_data_slices=%true.

А вот так это выглядит на практике. Оранжевая линия показывает потребление процессора на клике с включённой оптимизацией. В пике оптимизация позволяет экономить до 10% CPU всей клики

Экспорт системных таблиц с логами в Cypress

Теперь системные таблицы с логами со всех инстансов, такие как system.query_log, system.metric_log и т. д., можно экспортировать в Cypress.

Экспортирование таблиц включается и выключается в веб‑интерфейсе клики с помощью настройки Export system log tables на вкладке Advanced. По умолчанию экспортирование включено. При этой же настройке будет экспортироваться только таблица system.query_log. Но можно включить экспортирование и для любой другой системной таблицы, для этого необходимо указать в конфигурации ClickHouse движок SystemLogTableExporter для нужной таблицы.

Экспортированные таблицы будут доступны в Cypress по пути //sys/strawberry/chyt/{clique_alias}/artifacts/system_log_tables/{table_name}.

Поддержка типов данных

Bool

Ранее CHYT использовал кастомный тип YtBoolean для представления типа boolean из YT. Но теперь ClickHouse поддерживает свой собственный тип bool. Поэтому для версии 2.16 и выше этот тип будет использоваться вместо YtBoolean. YtBoolean останется как алиас к типу bool из ClickHouse.

Map

Добавлена поддержка типа данных Map.

date32, datetime64, timestamp64, interval64

Добавлена поддержка широких типов дат.

JSON

Добавлена поддержка JSON‑типа данных в режиме read‑only. При чтении JSON тип данных будет представляться как тип string, с которым можно работать с помощью JSON_*‑функций в ClickHouse.

Указания директории как базы данных для поддержки INFORMATION_SCHEMA

По умолчанию обращение к таблице в CHYT происходит через обращение по пути до неё. Понятий database и table нет в том виде, которые есть в ClickHouse. Мы добавили возможность указания директории в Cypress как database в настройках клики, но пока что в ручном режиме. После указания базы данных клика автоматически заполнит свои системные таблицы: system.databases, system.tables, system.columns.

Например, у вас есть директория с таблицами под названием //home/my_service/my_tables, в которой находится таблица table.

Укажем в блоке YT config настроек клики следующие параметры:

{
  "database_directories": {
    "db": "//home/my_service/my_tables"
  }
}

И теперь вы можете обращаться к таблице не через SELECT * FROM //home/my_service/my_tables/table, а через алиас пути SELECT * FROM db.table.

Базой данных по умолчанию является системная БД YT, но её тоже можно переназначить через параметр default_database в блоке ClickHouse config.

{
    "default_database": "db"
}

И тогда обращение можно сократить до SELECT * FROM table.

Добавление полей с метриками запросов в query_log

В query_log добавили колонку с CHYT‑специфичными метриками chyt_query_statistics.

Пример
\{
    "block_input_stream": \{
        "chunk_reader": \{
            "data_bytes_read_from_cache": \{
                "count": 2,
                "max": 0,
                "min": 0,
                "sum": 0
            \},
            "data_bytes_read_from_disk": \{
                "count": 2,
                "max": 0,
                "min": 0,
                "sum": 0
            \},
            "data_bytes_transmitted": \{
                "count": 2,
                "max": 29576,
                "min": 27289,
                "sum": 56865
            \},
            "data_io_requests": \{
                "count": 2,
                "max": 0,
                "min": 0,
                "sum": 0
            \},
            "meta_bytes_read_from_disk": \{
                "count": 2,
                "max": 0,
                "min": 0,
                "sum": 0
            \}
        \},
        "idle_time_us": \{
            "count": 4,
            "max": 2,
            "min": 0,
            "sum": 4
        \},
        "step_count": \{
            "count": 2,
            "max": 5,
            "min": 5,
            "sum": 10
        \},
        "wait_ready_event_time_us": \{
            "count": 23,
            "max": 8968,
            "min": 0,
            "sum": 32788
        \}
    \},
    "granule_min_max_filter": \{
        "can_skip": \{
            "count": 42,
            "last": 1,
            "max": 1,
            "min": 0,
            "sum": 21
        \}
    \},
    "phase_duration_us": \{
        "Execution": \{
            "count": 1,
            "last": 26406,
            "max": 26406,
            "min": 26406,
            "sum": 26406
        \},
        "Preparation": \{
            "count": 1,
            "last": 1029,
            "max": 1029,
            "min": 1029,
            "sum": 1029
        \},
        "Start": \{
            "count": 1,
            "last": 3995,
            "max": 3995,
            "min": 3995,
            "sum": 3995
        \}
    \},
    "storage_subquery": \{
        "read_us": \{
            "count": 1,
            "last": 3621,
            "max": 3621,
            "min": 3621,
            "sum": 3621
        \}
    \}
\}

А также колонки с версией клики chyt_version и FQDN‑именем машины, на которой выполнялся запрос chyt_instance_fqdn.

Обновление HTTP‑прокси

Параллельно с выпуском версии 2.16 мы обновили прокси и улучшили совместимость HTTP‑интерфейса с «железным» ClickHouse. Это упростит взаимодействие с официальными драйверами ClickHouse.

Авторизация через HTTP‑заголовок X‑ClickHouse‑Key

Теперь ClickHouse поддерживает определённый хедер для передачи ключа авторизации X‑ClickHouse‑Key:

  curl --location-trusted -H "X-ClickHouse-Key: $YT_TOKEN" "$PROXY/chyt?chyt.clique_alias=$CLIQUE_ALIAS&query=SELECT%201"
  1

Поддержка ClickHouse‑сессий на уровне HTTP‑прокси

Для HTTP‑интерфейса появилась возможность поддержки ClickHouse‑сессий. Если передать в запросе параметр session_id в виде произвольной строки, то последующие запросы с таким именем сессии будут попадать на один инстанс. Запросы исполнятся в рамках сессии.

Подробнее о параметрах настройки ClickHouse‑сессий можно прочитать в документации.

  curl --location-trusted -H "X-ClickHouse-Key: $YT_TOKEN" "$PROXY/chyt?chyt.clique_alias=$CLIQUE_ALIAS&session_id=test&query=SELECT%201"
  1

Запрос выполнится, создав сессию с именем test.

Передача запроса через параметр query внутри url

Запрос теперь можно передавать не только в теле, но и в пути (в параметре query), используя метод GET (как и в стандартном ClickHouse):

  curl --location-trusted -H "Authorization: OAuth $YT_TOKEN" "$PROXY/chyt?chyt.clique_alias=$CLIQUE_ALIAS&query=SELECT%201"
  1

Указание клики без звёздочки

Указывать алиас клики во всех наших интерфейсах теперь можно без звёздочки в начале.

Новый путь до CHYT HTTP Proxy

CHYT HTTP Proxy теперь доступен по пути /chyt вместо /query. Путь /query также остаётся для обратной совместимости, но для новых запросов рекомендуем использовать новый путь. У нового пути есть несколько обратно несовместимых изменений, которые описаны ниже. Путь /query остался обратно совместим. Все старые запросы будут работать без доработок.

Возможность указания кастомного порта в прокси для обхода /query в строке подключения

Администраторы кластера YT теперь могут сконфигурировать выделенный порт для CHYT на HTTP‑Proxy. Через этот порт будет доступен только CHYT без дополнительных путей /chyt и /query.

Это позволит применять его в библиотеках для работы с CH, которые не поддерживают явное указание URL.

Запросы с HTTP‑методом GET теперь read‑only

Запросы, сделанные по новому пути /chyt HTTP‑методом GET, теперь будут сохранять метод при проксировании и станут read‑only в терминах ClickHouse. То есть модифицировать таблицы в таких запросах не получится. Теперь для запросов INSERT/CREATE/DROP и т. д. обязательно использовать метод POST.

Указание клики внутри кластера через параметр user

Задать клику теперь можно через параметр user вместо прежнего HTTP‑параметра database. Параметр user указывается любым поддерживаемым способом авторизации: через заголовки Authorization: Basic, X‑ClickHouse‑User или через HTTP‑параметр user. Также можно задать клику через отдельный параметр chyt.clique_alias.

Что в итоге

Рекомендуем обновиться до актуальной версии 2.16. Вы получите расширенный набор типов данных и функций, оптимизацию производительности и возможность подключения кеша запросов.

Но предупредим: есть риски, связанные с добавлением новых типов данных. Например, тип timestamp при чтении теперь будет конвертироваться в datetime64 вместо uint64, что может сломать некоторые запросы. То же самое касается типа dict, который раньше читался как list(tuple(key, value)), а теперь будет как map(key, value).

Рекомендуем зафиксировать версию клики в настройках. Это защитит от непреднамеренного обновления при перезапуске клики.

Войдите, чтобы сохранить пост