Используйте JSON там, где это уместно
ClickHouse теперь предлагает собственный тип столбца JSON, предназначенный для полуструктурированных и динамических данных. Важно отметить, что это тип столбца, а не формат данных — вы можете вставлять JSON в ClickHouse как строку или через поддерживаемые форматы, такие как JSONEachRow, но это само по себе не означает использование типа столбца JSON. Тип JSON следует использовать только тогда, когда структура ваших данных является динамической, а не когда вы просто храните данные в формате JSON.
Когда использовать тип JSON
Тип JSON предназначен для выполнения запросов, фильтрации и агрегации отдельных полей внутри JSON-объектов с динамической или непредсказуемой структурой. Это достигается за счёт разбиения JSON-объектов на отдельные подстолбцы, что значительно сокращает объём считываемых данных и ускоряет запросы по выбранным полям по сравнению с альтернативами, такими как Map или разбор строк.
Однако это связано с важными компромиссами:
- Более медленные операции
INSERT— Разбиение JSON на подстолбцы, вывод типов и управление гибкими структурами хранения делает вставки медленнее по сравнению с хранением JSON в простом столбце типаString. - Медленнее при чтении целых объектов — Если нужно извлекать полные JSON-документы (а не отдельные поля), тип
JSONработает медленнее, чем чтение из столбца типаString. Накладные расходы на реконструкцию объектов из отдельных подстолбцов не дают преимуществ, если вы не выполняете запросы на уровне отдельных полей. - Накладные расходы на хранение — Поддержка отдельных подстолбцов добавляет структурные накладные расходы по сравнению с хранением JSON как одного строкового значения.
Используйте тип JSON, когда:
- Ваши данные имеют динамическую или непредсказуемую структуру с различающимися ключами в разных документах
- Типы полей или схемы со временем изменяются или различаются между записями
- Вам нужно выполнять запросы, фильтрацию или агрегирование по конкретным путям внутри объектов JSON, структуру которых невозможно заранее предсказать
- Ваш сценарий использования включает полуструктурированные данные, такие как логи, события или пользовательский контент с непоследовательными схемами
Используйте столбец String (или структурированные типы), когда:
- Структура ваших данных известна и стабильна — в этом случае используйте обычные столбцы или типы
Tuple,Array,DynamicлибоVariant - Документы
JSONрассматриваются как непрозрачные двоичные объекты, которые только сохраняются и извлекаются целиком без анализа на уровне полей - Вам не нужно выполнять запросы или фильтрацию по отдельным полям JSON в базе данных
JSONиспользуется только как формат передачи/хранения и не анализируется в ClickHouse
Если JSON — это непрозрачный документ, который не анализируется внутри базы данных и только сохраняется и затем извлекается, его следует хранить в столбце типа String. Преимущества типа JSON проявляются только тогда, когда вам нужно эффективно выполнять запросы, фильтрацию или агрегацию по конкретным полям внутри динамических структур JSON.
Вы также можете комбинировать подходы — использовать стандартные столбцы для предсказуемых верхнеуровневых полей и столбец JSON для динамических частей полезной нагрузки.
Особенности и рекомендации по использованию JSON
Тип JSON обеспечивает эффективное столбцовое хранение за счёт развёртывания путей в подстолбцы. Но вместе с гибкостью приходит и ответственность. Чтобы использовать его эффективно:
- Явно задавайте типы путей, используя подсказки в определении столбца, чтобы указать типы для известных подстолбцов и избежать ненужного вывода типов.
- Пропускайте пути, значения которых вам не нужны, с помощью SKIP и SKIP REGEXP, чтобы сократить объём хранимых данных и повысить производительность.
- Избегайте слишком больших значений
max_dynamic_paths— большие значения увеличивают потребление ресурсов и снижают эффективность. В качестве общего ориентира держите его ниже 10 000.
Подсказки типов — это не только способ избежать ненужного вывода типов, они полностью устраняют уровни косвенности при хранении и обработке. Пути JSON с подсказками типов всегда хранятся так же, как традиционные столбцы, обходясь без столбцов-дискриминаторов или динамического разрешения во время выполнения запроса. Это означает, что при хорошо заданных подсказках типов вложенные поля JSON достигают той же производительности и эффективности, как если бы они с самого начала были смоделированы как поля верхнего уровня. В результате для наборов данных, которые в основном стабильны, но всё же выигрывают от гибкости JSON, подсказки типов предоставляют удобный способ сохранить производительность без необходимости переработки вашей схемы или конвейера приёма.
Расширенные возможности
- JSON-столбцы могут использоваться в первичных ключах как любые другие столбцы. Для подстолбцов нельзя задавать кодеки.
- Они поддерживают интроспекцию через функции, такие как
JSONAllPathsWithTypes()иJSONDynamicPaths(). - Вы можете читать вложенные подобъекты, используя синтаксис
.^. - Синтаксис запросов может отличаться от стандартного SQL и может требовать специального приведения типов или использования операторов для вложенных полей.
Для получения дополнительной информации см. документацию по JSON в ClickHouse или ознакомьтесь с нашей публикацией в блоге Новый мощный тип данных JSON для ClickHouse.
Примеры
Рассмотрим следующий образец JSON, представляющий одну строку из набора данных Python PyPI:
Предположим, что эта схема статична и типы могут быть чётко определены. Даже если данные представлены в формате NDJSON (по одной JSON-строке на строку), нет необходимости использовать тип JSON для такой схемы. Просто опишите схему, используя классические типы.
и вставьте строки JSON:
Рассмотрим набор данных arXiv, содержащий 2,5 млн научных статей. Каждая строка в этом наборе данных, предоставленном в формате NDJSON, представляет собой опубликованную научную статью. Пример строки показан ниже:
Хотя приведённый здесь JSON из‑за вложенных структур довольно сложен, он предсказуем: число и тип полей не изменяются. Хотя для этого примера мы могли бы использовать тип JSON, мы можем явно задать структуру, используя типы Tuples и Nested:
Снова вставим данные в формате JSON:
Предположим, что был добавлен ещё один столбец tags. Если бы это был просто список строк, мы могли бы представить его в виде Array(String), но давайте предположим, что вы можете добавлять произвольные структуры тегов со смешанными типами (обратите внимание, что score — это строка или целое число). Наш модифицированный JSON-документ:
В этом случае мы можем представить документы arXiv либо целиком в формате JSON, либо просто добавить столбец tags типа JSON. Ниже приведены оба варианта:
Мы задаем подсказку о типе для столбца update_date в определении JSON, так как используем его в сортировке/как часть первичного ключа. Это помогает ClickHouse понять, что этот столбец не может быть null, и гарантирует, что он знает, какой подстолбец update_date использовать (для каждого типа их может быть несколько, поэтому без этого возникает неоднозначность).
Мы можем вставить данные в эту таблицу и затем посмотреть автоматически выведенную схему, используя функцию JSONAllPathsWithTypes и формат вывода PrettyJSONEachRow:
В качестве альтернативы мы могли бы смоделировать это, используя ранее описанную схему и JSON-столбец tags. Такой подход обычно предпочтительнее, так как сводит к минимуму необходимость дополнительных выводов со стороны ClickHouse:
Теперь мы можем вывести типы подстолбца tags.