Skip to main content
Тип столбца JSON готов к использованию в продакшне, начиная с ClickHouse 25.3+. Более ранние версии не рекомендуется использовать в продакшне.
Ваши данные поступают в формате JSON. ClickHouse предлагает несколько способов их хранения: от полностью типизированных столбцов до хранения в виде необработанного String. Правильный выбор зависит от того, насколько предсказуема ваша схема и нужны ли вам запросы по отдельным полям. Область охвата: Эта страница посвящена выбору схемы для хранения данных JSON. Она не охватывает форматы ввода/вывода JSON, функции JSON или синтаксис запросов. Общие сведения о самом типе столбца JSON см. в разделе Используйте JSON там, где это уместно. Предполагается: Знакомство с созданием таблиц ClickHouse, основами MergeTree и синтаксисом типов столбцов.

Быстрый выбор

  • Если у каждого поля известный стабильный тип и схема меняется редко Типизированные столбцы
  • Если большинство полей стабильны, но какая-то часть данных динамическая или непредсказуемая Гибридная схема (типизированные столбцы + JSON)
  • Если вся структура динамическая, а ключи в разных записях то появляются, то исчезают Нативный JSON-столбец
  • Если динамические поля представляют собой пары ключ-значение с единым типом значений (например, строковые теги или числовые метрики) Map вместо JSON
  • Если вы только сохраняете и извлекаете JSON-объект без запросов по отдельным полям Непрозрачное хранение в String
Не путайте JSON как формат и JSON как тип столбца. Вы можете вставлять данные в формате JSON (через JSONEachRow и т. д.) в типизированные столбцы, вообще не используя тип столбца JSON. Здесь речь идет о выборе типов столбцов, а не входных форматов.

Подробности о подходе

Типизированные столбцы

Когда использовать: Структура JSON полностью известна на этапе проектирования. Поля и типы не меняются от записи к записи. Даже сложные вложенные структуры (массивы объектов, вложенные словари) можно выразить с помощью типов Array, Tuple и Nested. Компромиссы: Для изменения схемы требуется ALTER TABLE. Непредусмотренные поля при вставке молча отбрасываются, если схема не была обновлена.
Настройка
Проверка
Обратите внимание
  • Если вы вставляете JSON-данные с JSONEachRow и JSON содержит поля, которых нет в схеме, ClickHouse по умолчанию молча их отбрасывает. Установите input_format_skip_unknown_fields в 0, если хотите вместо этого получать ошибки.

Гибридный подход (типизированные столбцы + JSON)

Когда использовать: Базовый набор полей стабилен (временные метки, ID, коды состояния), но часть данных динамическая. Например, пользовательские атрибуты, теги, метаданные или поля расширений, которые различаются от записи к записи. Компромиссы: Максимальная производительность на типизированных столбцах и гибкость в JSON-столбце. При этом 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-столбец

Когда использовать: Когда структура действительно непредсказуема и ключи появляются и исчезают от записи к записи. Схемы, создаваемые пользователями, системы плагинов или ингестия в озеро данных, где вы не контролируете исходную схему. Компромиссы: Вставка медленнее, чем в типизированные столбцы. Полное чтение объекта медленнее, чем у String. Дополнительные затраты хранилища на управление подстолбцами. Хорошо подходит для запросов по отдельным полям на конкретных путях.
Настройка
Используйте формат JSONAsObject при вставке целых JSON-документов в JSON-столбец. В нём каждая входная строка интерпретируется как полный объект JSON, сопоставленный со столбцом.Проверка
На что обратить внимание
  • Без подсказок типов ClickHouse определяет тип для каждого пути по первым встретившимся значениям. Если score приходит как "10" (строка) в одной записи и как 10 (целое число) в другой, для этого пути создаётся столбец-дискриминатор, и запросы становятся медленнее. Добавляйте подсказки для путей с известными типами.
  • Когда количество путей превышает max_dynamic_paths, значения сверх лимита перемещаются в общую структуру данных, что снижает производительность запросов. Отслеживайте это с помощью JSONDynamicPaths() и держите лимит ниже 10 000.
  • Каждый динамический путь поддерживает до max_dynamic_types (по умолчанию 32) различных типов данных. Если один путь превышает этот предел, дополнительные типы переключаются на общее хранилище Variant. Обычно это несущественно, если только в ваших данных нет сильно различающихся типов для одного и того же поля.

Непрозрачное хранение в String

Когда использовать: JSON-документы хранятся и извлекаются целиком, а затем передаются в приложение, архивируются или отправляются дальше по конвейеру. Без фильтрации по отдельным полям и агрегации внутри ClickHouse. Компромиссы: Самые быстрые вставки и самая простая схема. Запросы по отдельным полям невозможны без разбора во время выполнения (семейство 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, когда это плоские пары ключ-значение с единым типом значений.
Последнее изменение 23 июля 2026 г.