Использование логического "ИЛИ" в секции "ГДЕ" запроса (LogicalOrInTheWhereSectionOfQuery)¶
Тип | Поддерживаются языки |
Важность | Включена по умолчанию |
Время на исправление (мин) |
Теги |
---|---|---|---|---|---|
Дефект кода |
BSL |
Важный |
Да |
15 |
sql performance standard |
Описание диагностики¶
Не следует использовать ИЛИ
в секции ГДЕ
запроса. Это может привести к тому, что СУБД не сможет использовать
индексы таблиц и будет выполнять сканирование, что увеличит время работы запроса и вероятность возникновения блокировок.
Вместо этого следует разбить один запрос на несколько и объединить результаты.
Примеры¶
Например, запрос:
ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар
ГДЕ Артикул = "001" ИЛИ Цена = 10
следует заменить на запрос:
ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар ГДЕ Артикул = "001"
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Товар.Наименование ИЗ Справочник.Товары КАК Товар ГДЕ Цена = 10
Важно - текущая реализация диагностики срабатывает на любое
ИЛИ
в секцииГДЕ
и может выдавать ложные срабатывания для некоторых условий.
1) В основном условии оператор ИЛИ
можно использовать только для последнего из используемых или единственного поля индекса, когда оператор ИЛИ
можно заменить на оператор В
.
Правильно:
ГДЕ
Таблица.Поле = &Значение1
ИЛИ Таблица.Поле = &Значение2
т.к. можно переписать при помощи оператора В
(специально переписывать не нужно, можно оставить, как есть):
ГДЕ
Таблица.Поле В (&Значения)
Неправильно:
ГДЕ
Таблица.Поле1 = &Значение1
ИЛИ Таблица.Поле2 = &Значение2
нельзя переписать при помощи В
, но можно переписать при помощи ОБЪЕДИНИТЬ ВСЕ
(каждое поле Поле1 и Поле2 должны быть проиндексированы):
ГДЕ
Таблица.Поле1 = &Значение1
ОБЪЕДИНИТЬ ВСЕ
ГДЕ
Таблица.Поле2 = &Значение1
Примечание: заменить
ИЛИ
наОБЪЕДИНИТЬ ВСЕ
можно не всегда, убедитесь, что результат будет действительно тем же, что и приИЛИ
, перед тем, как применять.
2) В дополнительном условии оператор ИЛИ можно использовать без ограничений.
Правильно:
ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно использовать ИЛИ)
(Таблица.Поле2 = &Значение2 ИЛИ Таблица.Поле3 = &Значение3)
Правильно:
ГДЕ
(Таблица.Поле1 = &Значение1 ИЛИ Таблица.Поле1 = &Значение2)
И
(Таблица.Поле2 = &Значение3 ИЛИ Таблица.Поле2 = &Значение4)
т.к. можно переписать при помощи В (специально переписывать не нужно, можно оставить, как есть):
ГДЕ
Таблица.Поле1 В (&Значения1) // Основное условие
И Таблица.Поле2 В (&Значения2) // Дополнительное условие (или наоборот)
Источники¶
- Стандарт - Эффективные условия запросов, п.2
- Использование логического ИЛИ в условиях - Типичные причины неоптимальной работы запросов и методы оптимизации
- Интересный анализ SQL-запросов в различных СУБД (не про 1С) - Статья на Хабре
Сниппеты¶
Экранирование кода¶
// BSLLS:LogicalOrInTheWhereSectionOfQuery-off
// BSLLS:LogicalOrInTheWhereSectionOfQuery-on
Параметр конфигурационного файла¶
"LogicalOrInTheWhereSectionOfQuery": false