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 ) извлекает скалярное значение по пути JsonPath и возвращает его в заданном типе. Для использования JSON-индекса секция RETURNING <type> обязательна:

SELECT id, payload
FROM documents VIEW json_idx
WHERE JSON_VALUE(payload, '$.user.name' RETURNING Utf8) = "Charlie"u;

При проверке условий равенства либо вхождения значения в заданный список (IN) поиск в индексе осуществляется по токену «путь + значение», что обеспечивает наибольшую селективность. При других сравнениях (!=, <, >=, BETWEEN и др.) используется только токен пути, а итоговая точность сравнения обеспечивается пост-фильтром.

Параметры

Поддерживаются три способа передачи параметров запроса:

  1. Прямое сравнение результата JSON_VALUE с параметром:

    DECLARE $id AS Int64;
    SELECT * FROM documents VIEW json_idx
    WHERE JSON_VALUE(payload, '$.owner_id' RETURNING Int64) = $id;
    
  2. Проверка наличия результата в списке значений:

    DECLARE $tags AS List<Utf8>;
    SELECT * FROM documents VIEW json_idx
    WHERE JSON_VALUE(payload, '$.tag' RETURNING Utf8) IN $tags;
    
  3. Передача параметра в 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.

Предыдущая
Следующая