Работа с 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:
Строки также можно загружать непосредственно в запросе с помощью предложения FORMAT, например:
В этих примерах предполагается использование формата JSONEachRow. Также поддерживаются другие распространённые форматы JSON, примеры их загрузки приведены здесь.
Загрузка полуструктурированного JSON
В нашем предыдущем примере загружался JSON, который был статичным, с заранее известными именами ключей и типами. На практике так бывает не всегда — ключи могут добавляться, а их типы меняться. Это типично для сценариев, таких как данные обсервабилити.
ClickHouse обрабатывает такие случаи с помощью специального типа JSON.
Рассмотрим следующий пример из расширенной версии вышеупомянутого набора данных набор данных Python PyPI. Здесь мы добавили произвольный столбец tags со случайными парами ключ–значение.
Столбец tags здесь непредсказуем и поэтому его невозможно смоделировать в схеме данных. Чтобы загрузить эти данные, мы можем использовать нашу предыдущую схему, но добавить дополнительный столбец tags типа JSON:
Заполним таблицу тем же способом, что и исходный набор данных:
Обратите внимание на разницу в производительности при загрузке данных. Для JSON-столбца при вставке требуется определение типов, а также дополнительное место для хранения, если есть столбцы, содержащие значения более чем одного типа. Хотя тип JSON можно настроить (см. Проектирование схемы JSON) так, чтобы его производительность была сопоставима с явным объявлением столбцов, по умолчанию он намеренно остаётся гибким. Однако эта гибкость имеет свою цену.
Когда использовать тип JSON
Используйте тип JSON, когда ваши данные:
- Имеют непредсказуемые ключи, которые могут меняться со временем.
- Содержат значения с различными типами (например, путь может иногда содержать строку, а иногда число).
- Требуют гибкости схемы, когда строгая типизация невозможна.
Если структура ваших данных известна и стабильна, необходимость в типе JSON возникает редко, даже если ваши данные находятся в формате JSON. В частности, если ваши данные имеют:
- Плоскую структуру с известными ключами: используйте стандартные типы столбцов, например String.
- Предсказуемую вложенность: используйте типы Tuple, Array или Nested для таких структур.
- Предсказуемую структуру с различающимися типами значений: рассмотрите вместо этого использование типов Dynamic или Variant.
Вы также можете комбинировать подходы, как мы сделали в приведённом выше примере, используя статические столбцы для предсказуемых ключей верхнего уровня и один JSON-столбец для динамической части данных.