Map или тип JSON для ClickStack
Schema по умолчанию в ClickStack хранит атрибуты resource, scope, log и span в столбцах Map(LowCardinality(String), String). ClickHouse также поддерживает строго типизированный JSON type, а ClickStack поддерживает его использование вместо Map в бета-режиме.
Для типичных рабочих нагрузок обсервабилити рекомендуем оставить schema по умолчанию на основе Map. Тип JSON доступен пользователям, которые хотят оценить его на рабочих нагрузках с небольшим и стабильным набором ключей атрибутов, но для общего использования эта schema не рекомендуется.
Почему Map — рекомендуемый вариант по умолчанию
В данных обсервабилити преобладают атрибуты: атрибуты ресурса, атрибуты scope, а также атрибуты span и логов. Эти наборы обычно велики, имеют высокую кардинальность и поступают с высокой скоростью. Выбранная для этих атрибутов schema — главный фактор, определяющий стоимость приёма и структуру хранения.
Map(LowCardinality(String), String) хранит ключи и значения в единой структуре. Исторически недостаток Map состоял в том, что для чтения одного ключа приходилось читать весь столбец map целиком. Теперь это уже не так: ClickHouse поддерживает сериализация Map по бакетам, которая разбивает map на бакеты, поэтому запросы читают только нужные им бакеты. В сочетании с текстовыми индексами по ключам и значениям map — именно так настроена schema ClickStack по умолчанию — это делает Map быстрым для выборочного чтения без каких-либо дополнительных затрат на приём при появлении новых ключей.
На практике это означает:
- Стабильная стоимость приёма по мере роста числа ключей. Добавление нового ключа атрибута не меняет структуру столбцов на диске и не создаёт новые файлы столбцов. Стоимость приёма ограничена объёмом данных, а не кардинальностью ключей.
- Без взрывного роста метаданных. Количество файлов столбцов на диске не зависит от числа уникальных ключей атрибутов.
- Выборочный поиск через индексы. Текстовые индексы по ключам и значениям map позволяют выполнять точечный поиск без сканирования каждой строки.
- Предсказуемое поведение при высокой нагрузке. Map справляется со всплесками и бесcхемными наборами атрибутов, типичными для трассировки и логов, без накладных расходов на каждый ключ.
Почему не JSON по умолчанию
Тип JSON использует другой подход: при вставке ClickHouse динамически создаёт отдельный строго типизированный подстолбец для каждого обнаруженного пути. При чтении это выглядит привлекательно, поскольку читаются только запрошенные подстолбцы, типы сохраняются и приведение типов во время выполнения запроса не требуется.
Цена этого подхода проявляется на этапе приёма. Создание и сопровождение множества динамических подстолбцов увеличивает накладные расходы при записи и усложняет метаданные. Для рабочих нагрузок обсервабилити, где обычно встречаются очень большие или сильно меняющиеся наборы атрибутов и высокий объём приёма данных, эти накладные расходы оказываются существенными. Ограничение max_dynamic_paths позволяет сдержать ущерб, перенося лишние пути в общий столбец, но доступ к общему столбцу медленнее, чем к выделенным подстолбцам, а значит, снижается преимущество при чтении, ради которого JSON и выбирают.
Поскольку сериализация Map по бакетам устраняет большую часть исторических накладных расходов Map при чтении, преимущество JSON на этапе чтения больше не перевешивает его стоимость на этапе приёма для типичных рабочих нагрузок обсервабилити.
Когда JSON всё ещё может быть уместен
Тип JSON может быть разумным выбором, если все следующие условия выполняются одновременно:
- Набор ключей атрибутов небольшой и стабильный, то есть у вас не появляются тысячи уникальных ключей, а новые ключи возникают редко.
- Пропускная способность приёма умеренная по сравнению с кардинальностью атрибутов.
- Вам нужен строго типизированный доступ к атрибутам без CAST во время выполнения запроса (числа остаются числами, логические значения — логическими значениями).
- Вы готовы использовать бета-функцию в ClickStack и принимаете, что интеграция может измениться.
Если хотя бы одно из этих условий не выполняется, используйте schema на основе Map по умолчанию.
Бета-статус
Поддержка типа JSON в ClickStack — это бета-функция. Хотя сам тип JSON готов для продакшена в ClickHouse 25.3+, его интеграция с ClickStack всё ещё активно развивается и может иметь ограничения, в будущем измениться или содержать ошибки.
В ClickStack поддержка типа JSON в статусе бета доступна начиная с версии 2.0.4.
Включение поддержки JSON
Чтобы использовать schema с типом JSON вместо schema по умолчанию на основе Map, задайте следующие переменные окружения.
| Переменная | Где задаётся | Назначение |
|---|---|---|
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' | OTel collector | Создаёт schema в ClickHouse с использованием типа JSON. |
BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true | HyperDX (интерфейс ClickStack) | Включает поддержку запросов к schema с типом JSON на уровне приложения. Только для ClickStack Open Source. |
Управляемый ClickStack
Чтобы включить поддержку JSON в Управляемом ClickStack, до настройки коллектора обратитесь в службу поддержки по адресу support@clickhouse.com. Эту функцию также нужно включить в интерфейсе ClickStack (HyperDX) в ClickHouse Cloud.
Задайте OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' для коллектора. Например:
ClickStack с открытым исходным кодом
Установите OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' во всех развертываниях, включающих коллектор, а также BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true на уровне приложения HyperDX, чтобы можно было выполнять запросы к schema типа JSON.
Например:
Миграция с schema на основе Map на JSON
тип JSON не обеспечивает обратную совместимость с существующими schema на основе Map. При включении этой функции создаются новые таблицы с типом JSON, и требуется ручная миграция данных.
Чтобы выполнить миграцию со schemas на основе Map, используемых по умолчанию, выполните следующие шаги:
Остановите OTel коллектор
Переименуйте существующие таблицы и обновите источники данных
Переименуйте существующие таблицы и обновите источники данных в HyperDX.
Например:
Разверните коллектор
Разверните коллектор, задав OTEL_AGENT_FEATURE_GATE_ARG.
Перезапустите контейнер HyperDX с поддержкой JSON schema
Создайте новые источники данных
Создайте в HyperDX новые источники данных, указывающие на JSON-таблицы.
Перенос существующих данных (необязательно)
Чтобы перенести старые данные в новые JSON-таблицы:
Рекомендуется только для наборов данных размером менее ~10 миллиардов строк. Данные, ранее хранившиеся в типе Map, не сохраняли точность типов (все значения были строками). В результате эти старые данные будут отображаться в новой schema как строки, пока не устареют, поэтому на фронтенде потребуется приведение типов. Для новых данных типы будут сохраняться при использовании типа JSON.