#std658

Эффективные условия запросов

1.

Условия запросов пишите с учетом производительности. Цель: не допускать существенного роста времени выполнения при увеличении объема данных.

Поля основного условия в секциях ГДЕ, ПО и в параметрах виртуальных таблиц должны быть проиндексированы. Основное условие можно уточнять дополнительным условием, но объединять их нужно через И.

Важно учитывать структуру индексов:

  • для разных полей метаданных создаются разные индексы;
  • в одном запросе обычно используется только один индекс в основном условии;
  • основное условие лучше строить на автоматически создаваемых платформой индексах.

Основное условие — это условие, которое сильнее всего сокращает выборку. Его составляющие объединяются по И.

Дополнительное условие — это уточнение основного условия. Оно тоже объединяется с основным по И, но внутри может быть сложным: НЕ, <>, арифметика, функции и т.п.

В основном условии используйте только операции, которые позволяют поиск по индексу:

  • для первого и всех используемых полей индекса, кроме последнего: только = и И;
  • для последнего (или единственного) используемого поля индекса допустимы: =, >, <, >=, <=, ПОДОБНО, МЕЖДУ, В, ИЛИ (если приводится к В);
  • нельзя использовать арифметику, функции, отрицания и неравенства в основном условии.

Для индексации ориентируйтесь на место условия:

  • условия в ГДЕ и параметрах виртуальной таблицы: индексируйте поля основной таблицы выборки;
  • условия в ПО левого соединения: индексируйте поля правой таблицы;
  • условия в ПО внутреннего соединения: индексируйте поля таблицы с большим числом записей.

См. также:

1.1.

Требования раздела 1 можно не применять, если:

  • в таблицах всегда мало данных (менее 1000 записей);
  • запросы с такими условиями выполняются редко.
1.2.

Если записей много и требования раздела 1 выполнить невозможно:

  • преобразуйте условия (см. разделы 3 и 4);
  • добавьте заранее вычисляемые индексируемые поля и заполняйте их при записи;
  • если это не помогло, пересмотрите архитектуру решения.
2.

Оператор ИЛИ.

2.1.

В основном условии ИЛИ допустим только для последнего (или единственного) поля индекса, когда выражение можно привести к В.

Правильно

ГДЕ
    Таблица.Поле = &Значение1
    ИЛИ Таблица.Поле = &Значение2

Правильно / Эквивалентно (переписывать необязательно):

ГДЕ
    Таблица.Поле В (&Значения)

Неправильно

ГДЕ
    Таблица.Поле1 = &Значение1
    ИЛИ Таблица.Поле2 = &Значение2

Такое выражение к В не приводится. В ряде случаев его можно заменить на ОБЪЕДИНИТЬ ВСЕ (если это сохраняет семантику):

... ГДЕ
    Таблица.Поле1 = &Значение1

ОБЪЕДИНИТЬ ВСЕ

... ГДЕ
    Таблица.Поле2 = &Значение2

Примечание

Замена ИЛИ на ОБЪЕДИНИТЬ ВСЕ применима не всегда. Перед заменой проверьте, что результат выборки не изменится.

2.2.

В дополнительном условии оператор ИЛИ можно использовать без ограничений.

Правильно

ГДЕ
    Таблица.Поле1 = &Значение1 // Основное условие (индекс)
    И
    (Таблица.Поле2 = &Значение2 ИЛИ Таблица.Поле3 = &Значение3) // Дополнительное условие

Правильно

ГДЕ
    (Таблица.Поле1 = &Значение1 ИЛИ Таблица.Поле1 = &Значение2)
    И
    (Таблица.Поле2 = &Значение3 ИЛИ Таблица.Поле2 = &Значение4)

Правильно / Эквивалентно (переписывать необязательно):

ГДЕ
    Таблица.Поле1 В (&Значения1) // Основное условие
    И Таблица.Поле2 В (&Значения2) // Дополнительное условие
3.

Оператор ПОДОБНО.

В основном условии ПОДОБНО можно применять для последнего (или единственного) используемого поля индекса.

Функции обработки строк по возможности приводите к ПОДОБНО.

Неправильно

ГДЕ
    ПОДСТРОКА(Таблица.Поле, 1, 6) = "строка"

Правильно

ГДЕ
    Таблица.Поле ПОДОБНО "строка%"

Неправильно

ГДЕ
    ПОДСТРОКА(Таблица.Поле, 3, 6) = "строка"

Неправильно

ГДЕ
    Таблица.Поле ПОДОБНО "__строка%"

Литерал не должен начинаться с _ или %.

Правильно

Добавьте вычисляемое при записи поле, например с фрагментом ПОДСТРОКА(Таблица.Поле, 3, 6), проиндексируйте его и ищите по нему:

ГДЕ
    Таблица.ВычисляемоеПоле ПОДОБНО "строка%"
4.

Оператор МЕЖДУ.

В основном условии МЕЖДУ можно использовать для последнего (или единственного) поля индекса.

Функции работы с датами по возможности приводите к МЕЖДУ.

Неправильно

ГДЕ
    МЕСЯЦ(Таблица.Поле) = 1

Правильно

ГДЕ
    Таблица.Поле МЕЖДУ &ДатаНачалаМесяца И &ДатаКонцаМесяца

Пример границ:

  • ДатаНачалаМесяца = 01.01.2016;
  • ДатаКонцаМесяца = 31.01.2016 23:59:59.
5.

Выражение ВЫБОР используйте только в дополнительных условиях.

Правильно

ГДЕ
    Таблица.Поле1 = &Значение1 // Основное условие (индекс)
    И
    ВЫБОР
        КОГДА Таблица.Поле2 = &Значение2
            ТОГДА Таблица.Поле3 = &Значение3
        ИНАЧЕ Таблица.Поле4 = &Значение4
    КОНЕЦ

Неправильно

ГДЕ
    ВЫБОР // Основное условие (индекс использоваться не будет)
        КОГДА Таблица.Поле2 = &Значение2
            ТОГДА Таблица.Поле3 = &Значение3
        ИНАЧЕ Таблица.Поле4 = &Значение4
    КОНЕЦ
6.

Арифметические операции над полями выполняйте только в дополнительных условиях.

Правильно

ГДЕ
    Таблица.Поле1 = &Значение1 // Основное условие (индекс)
    И Таблица.Поле2 - 1 > 0 // Дополнительное условие

Неправильно

ГДЕ
    Таблица.Поле1 - 1 > 0 // Основное условие (поиск по индексу невозможен)
7.

Если для одного объекта и одного права пользователю назначены несколько ролей с разными условиями RLS, итоговый запрос к СУБД получит объединение условий через ИЛИ.

Это может ухудшить производительность и увеличить блокировки, даже если в исходном тексте запроса оператора ИЛИ не было.

Чтобы этого избежать:

  • проектируйте роли так, чтобы доступ к объекту для конкретного права давала одна роль;
  • если ролей несколько, задавайте одинаковые условия RLS для одного и того же права объекта.
См. также
Источник

https://its.1c.ru/db/v8std#content:658