Тип данных JSON
Ищете руководство?
Ознакомьтесь с нашим руководством по лучшим практикам работы с JSON, где приведены примеры, описаны расширенные возможности и рекомендации по использованию типа JSON.
Подробнее
Тип JSON хранит документы в формате JavaScript Object Notation (JSON) в одном столбце.
В ClickHouse Open-Source тип данных JSON признан готовым для промышленного использования начиная с версии 25.3. Не рекомендуется использовать этот тип в продакшене в более ранних версиях.
Чтобы объявить столбец типа JSON, используйте следующий синтаксис:
Где параметры в приведённом выше синтаксисе определяются следующим образом:
| Параметр | Описание | Значение по умолчанию |
|---|---|---|
max_dynamic_paths | Необязательный параметр, задающий, сколько путей может храниться отдельно в виде подстолбцов в одном отдельно хранимом блоке данных (например, в одной части данных таблицы MergeTree). Если этот лимит превышен, все остальные пути будут сохранены вместе в одной общей структуре, называемой общие данные. Существуют также способы изменить лимит на динамические пути без изменения этого параметра. | 1024 |
max_dynamic_types | Необязательный параметр в диапазоне от 1 до 255, задающий, сколько различных типов данных может храниться внутри одного столбца пути типа Dynamic в одном отдельно хранимом блоке данных (например, в одной части данных таблицы MergeTree). Если этот лимит превышен, все новые типы будут сохранены вместе в одной общей структуре, называемой shared variant. | 32 |
some.path TypeName | Необязательная подсказка типа для конкретного пути в JSON. Такие пути всегда будут храниться как подстолбцы с указанным типом. | |
SKIP path.to.skip | Необязательная подсказка для конкретного пути, который должен быть пропущен при разборе JSON. Такие пути никогда не будут сохранены в столбце JSON. Если указанный путь является вложенным объектом JSON, весь вложенный объект будет пропущен. | |
SKIP REGEXP 'path_regexp' | Необязательная подсказка с регулярным выражением, которое используется для пропуска путей при разборе 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.
Использование JSON в определении столбца таблицы
Использование CAST с ::JSON
Можно приводить различные типы данных с помощью специального синтаксиса ::JSON.
CAST из типа String в тип JSON
CAST из типа Tuple в JSON
Приведение типа из Map к JSON
JSON-пути хранятся в плоском виде. Это означает, что когда JSON-объект формируется на основе пути вида a.b.c,
невозможно однозначно определить, должен ли объект быть восстановлен как { "a.b.c" : ... } или как { "a": { "b": { "c": ... } } }.
Наша реализация всегда будет предполагать второй вариант.
Например:
вернет:
а не:
Чтение JSON-путей как подстолбцов
Тип JSON поддерживает чтение каждого пути как отдельного подстолбца.
Если тип запрашиваемого пути не указан в объявлении типа JSON,
то подстолбец для этого пути всегда будет иметь тип Dynamic.
Например:
Вы также можете использовать функцию getSubcolumn для чтения подстолбцов из типа JSON:
Если запрошенный путь отсутствует в данных, он будет заполнен значениями NULL:
Проверим типы данных возвращённых подстолбцов:
Как мы видим, для a.b тип — UInt32, как и было задано в объявлении типа JSON,
а для всех остальных подстолбцов тип — Dynamic.
Также можно читать подстолбцы столбца типа Dynamic, используя специальный синтаксис json.some.path.:TypeName:
Подстолбцы типа Dynamic можно привести к любому типу данных. При этом будет выброшено исключение, если внутренний тип в Dynamic нельзя привести к запрошенному типу:
Чтобы эффективно считывать подстолбцы из частей Compact MergeTree, убедитесь, что настройка MergeTree write_marks_for_substreams_in_compact_parts включена.
Чтение вложенных объектов JSON как подстолбцов
Тип JSON поддерживает чтение вложенных объектов как подстолбцов типа JSON с использованием специального синтаксиса json.^some.path:
Когда пути хранятся в базовой общей структуре данных (map), чтение подстолбцов вложенных объектов может быть неэффективным, поскольку для этого требуется сканировать всю общую структуру данных. При использовании map_with_buckets или advanced для сериализации общих данных чтение подстолбцов из общих данных значительно оптимизировано.
Чтение комбинированных подстолбцов JSON
Тип JSON поддерживает чтение пути как комбинированного подстолбца с использованием специального синтаксиса json.@some.path.
Комбинированный подстолбец для заданного пути возвращает:
- Литеральное значение, хранящееся по этому пути, в виде
Dynamic, если путь содержит литеральное значение. - Подобъект JSON по этому пути в виде
Dynamic, если путь не содержит литерального значения, но имеет вложенные подпути. NULL, если для этого пути не существует ни литерального значения, ни каких-либо подпутей.
Это полезно, когда в разных строках один и тот же путь может содержать либо скалярное значение, либо вложенный объект, и удобнее, чем отдельно выполнять запрос к подстолбцу с литеральным значением (json.a) и подстолбцу с подобъектом (json.^a).
В следующем примере сравниваются все три типа подстолбцов для пути a:
- Строка 1:
aсодержит литеральное значение42.json.aвозвращает его какDynamic(Int64),json.^aвозвращает пустой подобъект{}(уaнет вложенных ключей), аjson.@aвозвращает литеральное значение42. - Строка 2:
aсодержит вложенный объект.json.aвозвращаетNULL(по этому пути нет литерального значения),json.^aвозвращает подобъект какJSON, аjson.@aтакже возвращает этот подобъект какDynamic(JSON). - Строка 3:
aполностью отсутствует. Иjson.a, иjson.@aвозвращаютNULL, аjson.^aвозвращает пустой{}.
Когда пути хранятся в базовой (map) общей структуре данных, чтение объединённых подстолбцов может быть неэффективным, поскольку требует сканирования всей общей структуры данных. При сериализации общих данных map_with_buckets или advanced чтение подстолбцов из общей структуры данных значительно оптимизировано.
Определение типов для путей
Во время разбора JSON ClickHouse пытается определить наиболее подходящий тип данных для каждого пути в JSON.
Это работает аналогично автоматическому определению схемы по входным данным
и управляется теми же настройками:
- input_format_try_infer_dates
- input_format_try_infer_datetimes
- schema_inference_make_columns_nullable
- input_format_json_try_infer_numbers_from_strings
- input_format_json_infer_incomplete_types_as_strings
- input_format_json_read_numbers_as_strings
- input_format_json_read_bools_as_strings
- input_format_json_read_bools_as_numbers
- input_format_json_read_arrays_as_strings
- input_format_json_infer_array_of_dynamic_from_array_of_different_types
Рассмотрим несколько примеров:
Обработка массивов JSON-объектов
JSON-пути, содержащие массив объектов, интерпретируются как тип Array(JSON) и записываются в столбец Dynamic для этого пути.
Чтобы прочитать массив объектов, вы можете извлечь его из столбца Dynamic в виде подстолбца:
Как вы, возможно, заметили, параметры max_dynamic_types/max_dynamic_paths вложенного типа JSON были уменьшены по сравнению со значениями по умолчанию.
Это необходимо, чтобы избежать неконтролируемого увеличения числа подстолбцов во вложенных массивах объектов JSON.
Попробуем прочитать подстолбцы из вложенного столбца JSON:
Мы можем избежать необходимости указывать имена подстолбцов типа Array(JSON), используя специальный синтаксис:
Количество скобок [] после пути указывает уровень массива. Например, json.path[][] будет преобразовано в json.path.:Array(Array(JSON)).
Давайте проверим пути и типы внутри нашего Array(JSON):
Прочитаем подстолбцы столбца Array(JSON):
Также можно считывать подстолбцы вложенных объектов из вложенного столбца типа JSON:
Обработка JSON-ключей со значением NULL
В нашей реализации JSON значение null и отсутствие значения считаются эквивалентными:
Это означает, что невозможно определить, содержали ли исходные данные JSON какой‑либо путь со значением NULL или не содержали его вовсе.
Обработка ключей JSON с точками
Внутренне столбец JSON хранит все пути и значения в виде плоской структуры. Это означает, что по умолчанию следующие два объекта считаются одинаковыми:
Оба они во внутреннем представлении хранятся как пара: путь a.b и значение 42. При форматировании JSON мы всегда формируем вложенные объекты на основе частей пути, разделённых точкой:
Как видите, исходный JSON {"a.b" : 42} теперь имеет вид {"a" : {"b" : 42}}.
Это ограничение также приводит к ошибке при разборе корректных JSON-объектов, подобных этому:
Если вы хотите сохранить ключи с точками и избежать их интерпретации как вложенные объекты, вы можете включить настройку json_type_escape_dots_in_keys (доступна, начиная с версии 25.8). В этом случае при разборе JSON все точки в ключах будут экранированы в %2E и разэкранированы обратно при форматировании.
Чтобы прочитать ключ, в котором точка экранирована, как подстолбец, нужно использовать экранированную точку в имени подстолбца:
Примечание: из-за ограничений парсера и анализатора идентификаторов подстолбец json.`a.b` эквивалентен подстолбцу json.a.b и не сможет прочитать путь с экранированной точкой:
Кроме того, если вы хотите указать подсказку для JSON-пути, содержащего ключи с точками (или использовать эту подсказку в секциях SKIP/SKIP REGEX), необходимо экранировать точки в подсказке:
Чтение типа JSON из данных
Все текстовые форматы
(JSONEachRow,
TSV,
CSV,
CustomSeparated,
Values и т. д.) поддерживают чтение значений типа JSON.
Примеры:
Для текстовых форматов, таких как CSV/TSV/и т. д., тип JSON парсится из строки, содержащей объект JSON:
Достижение предела динамических путей внутри JSON
Тип данных JSON может хранить только ограниченное количество путей как отдельных внутренних подстолбцов.
По умолчанию этот предел равен 1024, но вы можете изменить его в объявлении типа с помощью параметра max_dynamic_paths.
Когда предел достигнут, все новые пути, вставляемые в столбец JSON, будут храниться в единой общей структуре данных.
По-прежнему можно считывать такие пути как подстолбцы,
но это может быть менее эффективно (см. раздел об общей структуре данных).
Этот предел необходим для того, чтобы избежать чрезмерно большого числа различных подстолбцов, которое может сделать таблицу непригодной к использованию.
Рассмотрим, что происходит при достижении предела в нескольких различных сценариях.
Достижение предела во время разбора данных
Во время разбора JSON-объектов из данных, когда предел достигнут для текущего блока данных,
все новые пути будут храниться в общей структуре данных. Мы можем использовать следующие две функции интроспекции: JSONDynamicPaths, JSONSharedDataPaths:
Как мы видим, после вставки путей e и f.g лимит был достигнут,
и они были помещены в общую структуру данных.
При слиянии частей данных в движках таблиц MergeTree
Во время слияния нескольких частей данных в таблице MergeTree столбец JSON в результирующей части данных может достичь предела динамических путей
и не сможет хранить все пути из исходных частей в виде подстолбцов.
В этом случае ClickHouse выбирает, какие пути останутся подстолбцами после слияния, а какие пути будут сохранены в общей структуре данных.
В большинстве случаев ClickHouse старается сохранить пути, содержащие
наибольшее количество ненулевых значений, и перенести самые редкие пути в общую структуру данных. Однако конкретное поведение зависит от реализации.
Рассмотрим пример такого слияния.
Сначала создадим таблицу со столбцом JSON, установим лимит динамических путей равным 3, а затем вставим значения с 5 различными путями:
Каждая операция вставки будет создавать отдельную часть данных со столбцом JSON, содержащим один путь:
Теперь объединим все части в одну и посмотрим, что получится:
Как мы видим, ClickHouse сохранил наиболее частые пути a, b и c и перенёс пути d и e в общую структуру данных.
Общая структура данных
Как было описано в предыдущем разделе, когда достигается предел max_dynamic_paths, все новые пути сохраняются в одной общей структуре данных.
В этом разделе мы рассмотрим детали общей структуры данных и то, как мы читаем из неё подстолбцы путей.
См. раздел "функции интроспекции" для подробностей о функциях, используемых для анализа содержимого столбца JSON.
Общая структура данных в памяти
В памяти общая структура данных — это просто подстолбец с типом Map(String, String), который хранит отображение от развёрнутого JSON-пути к двоично закодированному значению.
Чтобы извлечь из него подстолбец пути, мы просто итерируемся по всем строкам в этом столбце Map и пытаемся найти требуемый путь и его значения.
Общая структура данных в частях MergeTree
В таблицах MergeTree мы храним данные в частях данных, которые содержат всё на диске (локальном или удалённом). При этом данные на диске могут храниться иначе, чем в памяти.
В настоящее время в частях данных MergeTree используются три разных варианта сериализации общей структуры данных: map, map_with_buckets
и advanced.
Версия сериализации управляется настройками MergeTree object_shared_data_serialization_version и object_shared_data_serialization_version_for_zero_level_parts (часть нулевого уровня — это часть, создаваемая при вставке данных в таблицу; во время слияний части получают более высокий уровень).
Примечание: изменение формата сериализации общей структуры данных поддерживается только
для v3 версии сериализации объектов
Map
В версии сериализации map общие данные сериализуются как один столбец с типом Map(String, String), так же, как он хранится в
памяти. Чтобы прочитать подстолбец пути из такого типа сериализации, ClickHouse читает целиком столбец Map и
извлекает требуемый путь в памяти.
Эта сериализация эффективна для записи данных и чтения всего столбца JSON, но неэффективна для чтения подстолбцов путей.
Map with buckets
В версии сериализации map_with_buckets общие данные сериализуются как N столбцов («бакеты») с типом Map(String, String).
Каждый такой бакет содержит только подмножество путей. Чтобы прочитать подстолбец пути из такого типа сериализации, ClickHouse
читает целиком столбец Map из одного бакета и извлекает требуемый путь в памяти.
Эта сериализация менее эффективна для записи данных и чтения всего столбца JSON, но более эффективна для чтения подстолбцов путей,
поскольку считываются данные только из нужных бакетов.
Количество бакетов N управляется настройками MergeTree object_shared_data_buckets_for_compact_part (по умолчанию 8)
и object_shared_data_buckets_for_wide_part (по умолчанию 32).
Максимально допустимое значение для обеих настроек — 256.
Advanced
В версии сериализации advanced общие данные сериализуются в специальной структуре данных, которая максимально повышает производительность
чтения подстолбцов путей за счёт хранения дополнительной информации, позволяющей читать только данные запрошенных путей.
Эта сериализация также поддерживает бакеты, поэтому каждый бакет содержит только подмножество путей.
Эта сериализация довольно неэффективна для записи данных (поэтому не рекомендуется использовать её для частей нулевого уровня), чтение всего столбца JSON немного менее эффективно по сравнению с сериализацией map, но она очень эффективна для чтения подстолбцов путей.
Примечание: из-за хранения дополнительной информации внутри структуры данных размер занимаемого дискового пространства при этой сериализации больше по сравнению с
сериализациями map и map_with_buckets.
Более подробный обзор новых сериализаций общей структуры данных и деталей реализации см. в публикации в блоге.
Контроль количества динамических путей внутри JSON в частях MergeTree
Основной способ ограничить количество динамических путей в JSON — использовать параметр max_dynamic_paths в объявлении типа JSON.
Но изменение max_dynamic_paths для существующих столбцов требует выполнения ALTER TABLE <table> MODIFY COLUMN <column> JSON(max_dynamic_paths=K), что запустит фоновую мутацию, которая перезапишет все существующие части.
Такая мутация может быть очень ресурсоёмкой и влиять на производительность сервера до её завершения. Чтобы избежать этого, вы можете использовать следующие три настройки, которые позволяют изменить лимит на динамические пути в таблицах MergeTree для новых частей данных:
merge_max_dynamic_subcolumns_in_wide_part— настройка MergeTree, которая ограничивает количество динамических подстолбцов для каждого JSON-столбца при слиянии в широкую часть (Wide).merge_max_dynamic_subcolumns_in_compact_part— настройка MergeTree, которая ограничивает количество динамических подстолбцов для каждого JSON-столбца при слиянии в компактную часть (Compact).max_dynamic_subcolumns_in_json_type_parsing— сессионная настройка, которая ограничивает количество динамических подстолбцов для каждого JSON-столбца при разборе JSON-данных в JSON-столбец.
Примечание: ограничение на динамические пути не может превышать значение, указанное в параметре max_dynamic_paths, даже если значения описанных настроек больше.
Функции интроспекции
Существует несколько функций, которые помогают исследовать содержимое столбца JSON:
JSONAllPathsJSONAllPathsWithTypesJSONDynamicPathsJSONDynamicPathsWithTypesJSONSharedDataPathsJSONSharedDataPathsWithTypesdistinctDynamicTypesdistinctJSONPaths and distinctJSONPathsAndTypes
Примеры
Давайте исследуем содержимое набора данных GH Archive за 2020-01-01:
ALTER MODIFY COLUMN к типу JSON
Можно изменить существующую таблицу и сменить тип столбца на новый тип JSON. На данный момент поддерживается только ALTER для столбцов типа String.
Пример
Lazy Type Hints (экспериментально)
Эта функция является экспериментальной и требует включения настройки allow_experimental_json_lazy_type_hints.
Когда вы добавляете или изменяете подсказки типов для JSON-столбца с помощью ALTER TABLE ... MODIFY COLUMN, ClickHouse обычно перезаписывает все части, чтобы материализовать новые подсказки типов. Для таблиц с большим объёмом исторических данных (сотни терабайт) это может быть чрезвычайно затратно.
Lazy type hints позволяют добавлять подсказки типов как операцию, затрагивающую только метаданные, без перезаписи существующих данных:
- Старые части: подсказки типов применяются во время выполнения запроса путём приведения от
Dynamicк указанному типу - Новые части: подсказки типов материализуются во время операций
INSERT - Слияния: подсказки типов материализуются при слиянии частей
Это означает, что вы можете добавить подсказки типов мгновенно, а данные будут постепенно преобразовываться по мере выполнения обычных фоновых слияний.
Включение ленивых подсказок типов
Пример
Проверка отсутствия мутаций
Вы можете убедиться, что оператор ALTER завершился без мутаций, проверив таблицу system.mutations:
При включённых ленивых подсказках типов этот запрос не возвращает строк, что подтверждает, что операция выполнялась только на уровне метаданных.
Материализация подсказок типов
Чтобы материализовать подсказки типов в существующих данных, вы можете:
- Подождать фоновых слияний: ClickHouse автоматически материализует подсказки типов при слиянии частей
- Принудительно выполнить слияние: Используйте
OPTIMIZE TABLE test_lazy FINAL, чтобы немедленно объединить все части - Перезаписать части: Используйте
ALTER TABLE test_lazy REWRITE PARTS, чтобы перезаписать части с новыми метаданными
Ограничения
- Эта возможность является экспериментальной и может измениться в будущих версиях
- Преобразование типов во время выполнения запроса может иметь существенные накладные расходы по сравнению с предматериализованными типами, особенно для больших JSON-объектов
- Эта возможность применяется только при изменении
typed_paths(подсказок типов); другие параметры JSON, такие какmax_dynamic_paths,SKIPилиSKIP REGEXP, по-прежнему требуют Мутации
Сравнение значений типа JSON
Объекты JSON сравниваются аналогично значениям типа Map.
Например:
Примечание: если два пути содержат значения разных типов данных, они сравниваются в соответствии с правилом сравнения типа данных Variant.
Индексы пропуска данных для JSON
Индексы пропуска данных можно использовать со столбцами JSON двумя способами:
- Индексы по конкретным подстолбцам — создайте стандартный индекс пропуска данных для известного пути в JSON, как и для обычного столбца. В этом случае индексируются значения по этому пути.
- Индексы на основе путей с
JSONAllPaths— индексируйте набор путей, присутствующих в каждой грануле, чтобы пропускать гранулы, которые заведомо не могут содержать запрашиваемый путь.
Индексы для конкретных подстолбцов
Вы можете создать индекс пропуска данных для любого подстолбца JSON, используя тот же синтаксис, что и для обычных столбцов.
Работает любой поддерживаемый тип индекса (minmax, set, bloom_filter, tokenbf_v1, ngrambf_v1 и т. д.).
Есть два способа указать подстолбец JSON в выражении индекса:
- Типизированный путь, объявленный в подсказке типа JSON, — доступ по имени напрямую:
json.a. - Динамический путь с явным приведением типа — используйте синтаксис приведения
:::json.b::String.
Также можно использовать выражения, объединяющие несколько подстолбцов, например json.a || json.b::String.
Пример
Индекс minmax для типизированного подстолбца data.sensor_id ограничивает сканирование соответствующими гранулами:
Индекс bloom_filter для подстолбца data.location::String с приведением типа также работает:
Индексы на основе путей с JSONAllPaths
Индексы пропуска данных также можно создавать для столбцов JSON с помощью функции JSONAllPaths.
Это аналогично созданию индексов пропуска данных для столбцов Map через mapKeys: индекс хранит набор JSON-путей, присутствующих в каждой грануле, и использует его, чтобы пропускать гранулы, которые не могут содержать запрашиваемый путь.
Поддерживаемые типы индексов
JSONAllPaths можно использовать со следующими типами индексов пропуска данных:
bloom_filter— поддерживаетequals,inиIS NOT NULL.tokenbf_v1— поддерживаетequalsиIS NOT NULL.ngrambf_v1— поддерживаетequalsиIS NOT NULL.text(инвертированный индекс) — поддерживаетequals,inиIS NOT NULL.
Пример
Вы можете использовать EXPLAIN indexes = 1, чтобы убедиться, что индекс пропуска данных используется. Если путь существует только в одной части, индекс пропускает другую часть:
Если путь отсутствует ни в одной части, пропускаются все части и гранулы:
IS NOT NULL также использует индекс — он пропускает гранулы, где путь отсутствует (поскольку в этом случае значение было бы NULL):
Как это работает
Выражение JSONAllPaths(json_column) возвращает Array(String), содержащий все пути, присутствующие в значении JSON.
Индекс пропуска данных сохраняет эти строки путей в своей структуре данных (фильтр Блума или инвертированный индекс).
Когда запрос фильтрует по json.some.path, индекс проверяет, присутствует ли строка "some.path" в индексе для каждой гранулы, и пропускает гранулы, в которых она отсутствует.
Безопасность при отсутствии путей
Когда путь JSON отсутствует в грануле, подстолбец вычисляется как:
NULLдля типаDynamic(например,json.path) и подстолбцов типаNullable(например,json.path.:Int64) — сравнения сNULLвсегда возвращают false, поэтому пропуск безопасен.- Значение типа по умолчанию для выражений
CASTбезNullable(например,json.path::Int64дает0, если путь отсутствует) — пропуск безопасен только тогда, когда сравниваемое значение отличается от значения по умолчанию. Индекс автоматически учитывает это различие.
Рекомендации по более эффективному использованию типа JSON
Прежде чем создавать столбец JSON и загружать в него данные, учитывайте следующие рекомендации:
- Проанализируйте свои данные и укажите как можно больше подсказок по путям с указанием типов. Это сделает хранение и чтение гораздо более эффективными.
- Продумайте, какие пути вам понадобятся, а какие — никогда. Укажите пути, которые вам не нужны, в разделе
SKIP, а при необходимости — в разделеSKIP REGEXP. Это улучшит эффективность хранения. - Не устанавливайте параметр
max_dynamic_pathsна слишком большие значения, так как это может сделать хранение и чтение менее эффективными. Хотя это сильно зависит от системных параметров, таких как память, CPU и т.д., в качестве общего ориентира не следует устанавливатьmax_dynamic_pathsболее 10 000 для хранилища на локальной файловой системе и 1024 для хранилища на удалённой файловой системе.