Загрузка JSON
Ниже приведены очень простые примеры загрузки структурированных и полуструктурированных данных в формате JSON. Для более сложного JSON, включая вложенные структуры, см. руководство Проектирование схемы JSON.
Загрузка структурированного JSON
В этом разделе предполагается, что данные находятся в формате NDJSON (Newline delimited JSON — JSON, где объекты разделены переводами строки), который в ClickHouse известен как JSONEachRow, и хорошо структурированы, то есть имена и типы столбцов фиксированы. Формат NDJSON является предпочтительным для загрузки JSON из‑за своей компактности и эффективного использования места, но поддерживаются и другие форматы как для ввода, так и вывода.
Рассмотрим следующий пример JSON, представляющий строку из набора данных Python PyPI:
Чтобы загрузить этот JSON-объект в ClickHouse, необходимо определить схему таблицы.
В этом простом случае наша структура статична, имена столбцов известны, а их типы чётко определены.
Хотя ClickHouse и поддерживает полуструктурированные данные через тип JSON, где имена ключей и их типы могут быть динамическими, здесь в этом нет необходимости.
В случаях, когда ваши столбцы имеют фиксированные имена и типы, и не ожидается появление новых столбцов, в продуктивной среде всегда следует предпочитать статически определённую схему.
Тип JSON предпочтителен для очень динамичных данных, где имена и типы столбцов часто меняются. Этот тип также полезен для прототипирования и исследования данных.
Простая схема для этого показана ниже, где ключи JSON сопоставляются с именами столбцов:
Здесь мы выбрали ключ сортировки с помощью оператора ORDER BY. Дополнительные сведения о ключах сортировки и о том, как их выбирать, см. здесь.
ClickHouse может загружать JSON-данные в нескольких форматах, автоматически определяя тип по расширению и содержимому. Мы можем читать JSON-файлы для указанной выше таблицы с помощью функции S3:
Обратите внимание, что нам не нужно явно указывать формат файла. Вместо этого мы используем glob‑шаблон, чтобы прочитать все файлы *.json.gz в бакете. ClickHouse автоматически определяет, что формат — JSONEachRow (ndjson), по расширению и содержимому файла. Формат можно указать вручную с помощью параметризованных функций на случай, если ClickHouse не сможет определить его автоматически.
Указанные выше файлы также сжаты. ClickHouse автоматически определяет и обрабатывает их.
Чтобы загрузить строки из этих файлов, мы можем использовать INSERT INTO SELECT:
┌───────date─┬─country_code─┬─project────────────┬─type──┬─installer────┬─python_minor─┬─system─┬─version─┐ │ 2022-05-26 │ CN │ clickhouse-connect │ sdist │ bandersnatch │ │ │ 0.0.7 │ │ 2022-05-26 │ CN │ clickhouse-connect │ sdist │ bandersnatch │ │ │ 0.0.7 │ └────────────┴──────────────┴────────────────────┴───────┴──────────────┴──────────────┴────────┴─────────┘
2 строки в наборе. Время выполнения: 0.005 сек. Обработано 8.19 тысяч строк, 908.03 KB (1.63 миллиона строк/с., 180.38 MB/с.)
В этих примерах используется формат JSONEachRow. Поддерживаются и другие распространённые форматы JSON; примеры их загрузки приведены здесь.
Загрузка полуструктурированного JSON
В нашем предыдущем примере мы загружали JSON с фиксированной структурой и хорошо известными именами ключей и типами. На практике так бывает не всегда — ключи могут добавляться, а их типы меняться. Это часто встречается в сценариях, связанных с данными для наблюдаемости (Observability).
ClickHouse обрабатывает такие случаи с помощью специализированного типа JSON.
Рассмотрим следующий пример из расширенной версии описанного выше набора данных Python PyPI dataset. Здесь мы добавили произвольный столбец tags со случайными парами «ключ–значение».
Столбец tags здесь непредсказуем и, следовательно, его невозможно смоделировать. Чтобы загрузить эти данные, мы можем использовать нашу предыдущую схему, добавив дополнительный столбец tags типа JSON:
Заполним таблицу тем же способом, что и исходный набор данных:
Обратите внимание на разницу в производительности при загрузке данных. Для JSON-столбца при вставке требуется определение типов, а также дополнительное место для хранения, если есть столбцы, содержащие значения более чем одного типа. Хотя тип JSON можно настроить (см. Проектирование схемы JSON) так, чтобы его производительность была сопоставима с явным объявлением столбцов, по умолчанию он намеренно остаётся гибким. Однако эта гибкость имеет свою цену.
Когда использовать тип JSON
Используйте тип JSON, когда ваши данные:
- Имеют непредсказуемые ключи, которые могут меняться со временем.
- Содержат значения с различными типами (например, путь может иногда содержать строку, а иногда число).
- Требуют гибкости схемы, когда строгая типизация невозможна.
Если структура ваших данных известна и стабильна, необходимость в типе JSON возникает редко, даже если ваши данные находятся в формате JSON. В частности, если ваши данные имеют:
- Плоская структура с известными ключами: используйте стандартные типы столбцов, например String.
- Предсказуемая вложенность: используйте типы Tuple, Array или Nested для таких структур.
- Предсказуемая структура с изменяющимися типами: в таком случае рассмотрите использование типов Dynamic или Variant.
Вы также можете комбинировать подходы, как показано в приведённом выше примере, используя статические столбцы для предсказуемых ключей верхнего уровня и один JSON-столбец для динамической части данных.