VIEW (JSON-индекс)
Для выполнения запроса SELECT над строковой таблицей с явным использованием JSON-индекса используйте выражение VIEW:
SELECT ...
FROM documents VIEW json_idx
WHERE <предикат на основе JSON_EXISTS / JSON_VALUE>
ORDER BY ...
В примере запроса выше documents — это имя таблицы, содержащей колонку типа Json или JsonDocument, а json_idx — имя созданного над этой колонкой JSON-индекса.
Если предикат не поддерживается для выполнения через JSON-индекс, запрос с явным указанием выражения VIEW завершается ошибкой на этапе компиляции. Без выражения VIEW оптимизатор не сможет выбрать этот индекс для такого предиката, и запрос будет выполнен другим способом (например, выбором другого индекса, либо полным сканированием основной таблицы).
Примечание
JSON-индекс может быть выбран оптимизатором автоматически при условии соответствия предиката требованиям для использования индекса. Для отладки и гарантированного использования индекса указывайте его явно с помощью VIEW IndexName.
Описание поддерживаемых предикатов см. в разделе Поддерживаемые предикаты.
Автоматический выбор индекса
Если предикат WHERE содержит вызовы JSON_EXISTS / JSON_VALUE по индексированной JSON-колонке, оптимизатор может задействовать JSON-индекс без явного указания VIEW. Автоматический выбор подчиняется следующим правилам:
- JSON-индекс рассматривается оптимизатором с наименьшим приоритетом — это запасной вариант, который выбирается только после того, как остальные способы доступа исключены.
- JSON-индекс не выбирается, если запрос уже может быть обслужен первичным ключом или другим, более специфичным вторичным индексом.
- Явное указание
VIEWпереопределяет решение оптимизатора и принудительно включает использование индекса. - Все индексируемые подвыражения в одном запросе должны ссылаться на одну и ту же индексированную JSON-колонку. Если объединить через
AND/ORпредикаты по разным индексированным колонкам, автоматический выбор не применяется.
Примечание
Автоматический выбор JSON-индекса работает на основе системы правил (rule-based): он использует структуру запроса и метаданные схемы, без статистики данных. Логика выбора может измениться в будущих версиях YDB, поэтому для гарантированного использования индекса указывайте его явно через VIEW.
JSON_EXISTS
JSON_EXISTS(doc, jsonpath) проверяет существование пути или значения внутри JSON-документа:
SELECT id, payload
FROM documents VIEW json_idx
WHERE JSON_EXISTS(payload, '$.user.id');
JSON-индекс поддерживает практически весь синтаксис JsonPath, за исключением вложенных предикатов и булевых выражений на уровне контекстного объекта ($) в JSON_EXISTS. Более сложный пример поддерживаемого выражения:
SELECT id, payload
FROM documents VIEW json_idx
WHERE JSON_EXISTS(payload, '$.user ? (@.id > 100)');
JSON_VALUE
JSON_VALUE(doc, jsonpath RETURNING RETURNING <type> обязательна:
SELECT id, payload
FROM documents VIEW json_idx
WHERE JSON_VALUE(payload, '$.user.name' RETURNING Utf8) = "Charlie"u;
При проверке условий равенства либо вхождения значения в заданный список (IN) поиск в индексе осуществляется по токену «путь + значение», что обеспечивает наибольшую селективность. При других сравнениях (!=, <, >=, BETWEEN и др.) используется только токен пути, а итоговая точность сравнения обеспечивается пост-фильтром.
Параметры
Поддерживаются три способа передачи параметров запроса:
-
Прямое сравнение результата
JSON_VALUEс параметром:DECLARE $id AS Int64; SELECT * FROM documents VIEW json_idx WHERE JSON_VALUE(payload, '$.owner_id' RETURNING Int64) = $id; -
Проверка наличия результата в списке значений:
DECLARE $tags AS List<Utf8>; SELECT * FROM documents VIEW json_idx WHERE JSON_VALUE(payload, '$.tag' RETURNING Utf8) IN $tags; -
Передача параметра в JsonPath через секцию
PASSING:DECLARE $v AS Int64; SELECT * FROM documents VIEW json_idx WHERE JSON_EXISTS(payload, '$.k ? (@ == $v)' PASSING $v AS v);
Комбинации AND и OR
JSON_EXISTS и JSON_VALUE над одной JSON-колонкой могут объединяться в одном WHERE операторами AND и OR:
SELECT id, payload
FROM documents VIEW json_idx
WHERE JSON_VALUE(payload, '$.user.name' RETURNING Utf8) = "Charlie"u
AND JSON_VALUE(payload, '$.user.id' RETURNING Int64) BETWEEN 100 AND 200;
Примечание
Выполнение выборки через JSON-индекс может использовать только подмножество выражений на основе JSON_EXISTS и JSON_VALUE (см. Поддерживаемые предикаты). Условия, не подпадающие под эти правила (например, отрицания, сравнения с другой колонкой, сравнение двух JSON_VALUE из разных колонок), не индексируются; в AND они переходят в пост-фильтр, в OR приводят к отказу от использования индекса по всей группе условий, объединённой через OR.