Тип столбца JSON готов к использованию в продакшне, начиная с ClickHouse 25.3+. Более ранние версии не рекомендуется использовать в продакшне.
Быстрый выбор
- Если у каждого поля известный стабильный тип и схема меняется редко → Типизированные столбцы
- Если большинство полей стабильны, но какая-то часть данных динамическая или непредсказуемая → Гибридная схема (типизированные столбцы + JSON)
- Если вся структура динамическая, а ключи в разных записях то появляются, то исчезают → Нативный JSON-столбец
- Если динамические поля представляют собой пары ключ-значение с единым типом значений (например, строковые теги или числовые метрики)
→
Mapвместо JSON - Если вы только сохраняете и извлекаете JSON-объект без запросов по отдельным полям → Непрозрачное хранение в String
Не путайте JSON как формат и JSON как тип столбца. Вы можете вставлять данные в формате JSON (через
JSONEachRow и т. д.) в типизированные столбцы, вообще не используя тип столбца JSON. Здесь речь идет о выборе типов столбцов, а не входных форматов.Подробности о подходе
Типизированные столбцы
Array, Tuple и Nested.
Компромиссы: Для изменения схемы требуется ALTER TABLE. Непредусмотренные поля при вставке молча отбрасываются, если схема не была обновлена.
Настройка, проверка и подводные камни
Настройка, проверка и подводные камни
НастройкаПроверкаОбратите внимание
- Если вы вставляете JSON-данные с
JSONEachRowи JSON содержит поля, которых нет в схеме, ClickHouse по умолчанию молча их отбрасывает. Установитеinput_format_skip_unknown_fieldsв0, если хотите вместо этого получать ошибки.
Гибридный подход (типизированные столбцы + JSON)
Настройка, проверка и подводные камни
Настройка, проверка и подводные камни
НастройкаПроверкаОбратите внимание
- Используйте подсказки типов для JSON-путей, которые известны заранее. Подсказки обходят столбец-дискриминатор и сохраняют путь как обычный типизированный столбец — с той же производительностью и без накладных расходов.
- Используйте
SKIPилиSKIP REGEXPдля путей, которые вы никогда не запрашиваете (отладочные метаданные, внутренние ID трассировки), чтобы экономить хранилище и уменьшать число подстолбцов. - Устанавливайте
max_dynamic_pathsпропорционально числу различных путей, которые вы действительно запрашиваете. Значение по умолчанию (1024) подходит для большинства случаев. Уменьшите его, если динамическая часть у вас небольшая. - Не устанавливайте
max_dynamic_pathsвыше 10,000. Высокие значения увеличивают потребление ресурсов и снижают эффективность.
Ключи с точкамиКлючи с точками (например,
http.status_code) по умолчанию трактуются как вложенные пути, поэтому {"http.status_code": 200} хранится так же, как {"http": {"status_code": 200}}. Это часто встречается в атрибутах OTel. Используйте подсказки типов, чтобы управлять тем, как хранятся пути с точками, или включите json_type_escape_dots_in_keys (25.8+).Нативный JSON-столбец
Настройка, проверка и подводные камни
Настройка, проверка и подводные камни
НастройкаИспользуйте формат На что обратить внимание
JSONAsObject при вставке целых JSON-документов в JSON-столбец. В нём каждая входная строка интерпретируется как полный объект JSON, сопоставленный со столбцом.Проверка- Без подсказок типов ClickHouse определяет тип для каждого пути по первым встретившимся значениям. Если
scoreприходит как"10"(строка) в одной записи и как10(целое число) в другой, для этого пути создаётся столбец-дискриминатор, и запросы становятся медленнее. Добавляйте подсказки для путей с известными типами. - Когда количество путей превышает
max_dynamic_paths, значения сверх лимита перемещаются в общую структуру данных, что снижает производительность запросов. Отслеживайте это с помощьюJSONDynamicPaths()и держите лимит ниже 10 000. - Каждый динамический путь поддерживает до
max_dynamic_types(по умолчанию 32) различных типов данных. Если один путь превышает этот предел, дополнительные типы переключаются на общее хранилище Variant. Обычно это несущественно, если только в ваших данных нет сильно различающихся типов для одного и того же поля.
Непрозрачное хранение в String
JSONExtract), а это плохо масштабируется.
Настройка, проверка и подводные камни
Настройка, проверка и подводные камни
НастройкаПроверкаНа что обратить внимание
- Если требования изменятся и позже вам понадобятся запросы по отдельным полям, придётся создать новую таблицу с типизированными столбцами или JSON-столбцами и выполнить дозагрузку данных. Если есть хоть какая-то вероятность, что вам потребуется обращаться к отдельным полям, лучше сразу выбрать гибридный подход.
- Функции
JSONExtractразбирают строку при каждом запросе. Это приемлемо для разового анализа, но не для панелей мониторинга в продакшн и не для рабочих нагрузок с высоким QPS. - Если JSON-полезная нагрузка велика, рассмотрите кодеки сжатия (
ZSTD) для столбца String — такие данные хорошо сжимаются.
Сравнение
Когда лучше подходит Map
Map(String, T) проще и эффективнее, чем JSON-столбец. Типичные примеры: строковые теги (Map(String, String)), числовые метрики (Map(String, Float64)) или feature flags (Map(String, Bool)).
Map поддерживает фильтрацию на уровне ключей (tags['env'] = 'prod'), хранится дешевле, чем JSON, и позволяет избежать накладных расходов на подстолбцы, характерных для типа JSON. Обратите внимание, что поиск по ключу по умолчанию выполняет линейное сканирование map — это нормально для небольших наборов тегов, но для map со 100+ ключами стоит рассмотреть сериализацию with_buckets. Используйте JSON, когда значения имеют смешанные типы или структура содержит вложенные данные, — используйте Map, когда это плоские пары ключ-значение с единым типом значений.
- Используйте JSON там, где это уместно — когда использовать тип столбца JSON, а когда — альтернативы
- Справочник по типу данных JSON — полный синтаксис для подсказок типов, SKIP, max_dynamic_paths и функций интроспекции
- Выбор типов данных — общие рекомендации по выбору типов данных
- A New Powerful JSON Data Type for ClickHouse — подробный разбор архитектуры хранения типа JSON
- Справочник по форматам JSON — форматы ввода/вывода для данных JSON (JSONEachRow, JSONAsObject и т. д.)