Как правильно и эффективно располагать условия в запросе 1С: влияние на быстродействие

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При написании запросов в системе 1С:Предприятие часто возникает вопрос: имеет ли значение порядок следования условий в секции ГДЕ? Например, что должно идти первым — отбор по периоду или проверка флага Проведен? Кажется, что это мелочь, но понимание внутренней механики работы СУБД (система управления базами данных) позволяет писать по-настоящему быстрые и стабильные приложения. В этой статье мы подробно разберем, как СУБД обрабатывает ваши условия и на что действительно стоит обращать внимание.

Оптимизатор запросов: кто на самом деле управляет порядком

Разберем основной миф: многие разработчики полагают, что СУБД вычисляет условия строго слева направо (или сверху вниз), как это происходит в обычном коде на встроенном языке 1С. Однако SQL — это декларативный язык. Вы описываете, что хотите получить, а СУБД сама решает, как это сделать наиболее оптимальным способом.

Проанализируем работу Query Optimizer (оптимизатора запросов). Когда запрос попадает на SQL-сервер, оптимизатор строит план выполнения. Он анализирует статистику распределения данных в таблицах и «взвешивает» каждое условие. Если статистика говорит, что условие по дате отсечет 99% записей, а условие по признаку проведения — только 5%, оптимизатор применит фильтр по дате первым, вне зависимости от того, как вы написали это в тексте запроса.

Рассмотрим пример из обсуждения:


// Вариант 1
ГДЕ Док.Проведен И Док.Дата МЕЖДУ &Начало И &Конец

// Вариант 2
ГДЕ Док.Дата МЕЖДУ &Начало И &Конец И Док.Проведен

Для современного SQL-сервера эти записи чаще всего будут эквивалентны. Оптимизатор переставит их так, чтобы минимизировать количество чтений с диска.

Понятие селективности данных

Выясним причину, по которой опытные разработчики все же рекомендуют определенный порядок. Это связано с понятием селективности. Селективность — это способность условия отфильтровывать данные. Чем меньше записей остается после применения фильтра, тем выше его селективность.

  1. Высокая селективность: Отбор по уникальному номеру, ссылке или узкому периоду дат.
  2. Низкая селективность: Отбор по булеву полю (Проведен, ПометкаУдаления) или по перечислению с малым количеством значений (например, Статус).

Несмотря на умные алгоритмы SQL, хорошим тоном считается располагать условия от наиболее селективных к менее селективным. Это упрощает чтение кода коллегам и помогает в тех редких случаях, когда статистика СУБД устарела или не может быть корректно применена.

Индексация полей Проведен и Дата в 1С

Посмотрим на то, как платформа 1С проектирует таблицы в базе данных. Для большинства документов автоматически создаются индексы, включающие дату. Обычно это составной индекс Период + Ссылка. Поле Проведен также часто включается в составные индексы в типовых конфигурациях или платформенных механизмах.

Важно понимать: чтобы индекс по дате работал (Index Seek), условие должно быть SARGable (Search Argumentable). Использование конструкций МЕЖДУ или сравнений >= и <= — это правильный путь. Если же вы примените функцию к полю даты, например:

ГДЕ МЕСЯЦ(Док.Дата) = 1 И Док.Проведен

СУБД будет вынуждена просканировать всю таблицу (Index Scan), так как значение функции нельзя заранее найти в индексе. В этом случае порядок условий тем более не спасет производительность.

Опасность «короткого замыкания» в SQL

Проанализируем интересную ситуацию, поднятую в обсуждении: работает ли правило «короткого замыкания» (short-circuit evaluation), когда второе условие не вычисляется, если первое ложно? В языках программирования это норма, но в SQL-запросах — нет.

Рассмотрим пример с потенциальной ошибкой деления на ноль:


ВЫБРАТЬ
    втТаблица.Поле1 КАК Поле1
ИЗ
    втТаблица КАК втТаблица
ГДЕ
    втТаблица.Поле1 > 5 
    И 10 / (втТаблица.Поле1 - 5) > 0

В обычном коде 1С, если Поле1 равно 5, первое условие даст Ложь, и до деления дело не дойдет. В SQL-запросе оптимизатор может решить сначала вычислить правую часть или выполнить их параллельно. Если в таблице есть запись со значением 5, запрос может упасть с ошибкой, независимо от порядка условий в ГДЕ. Это еще раз доказывает, что полагаться на порядок написания условий для управления логикой вычислений — рискованная стратегия.

Практические рекомендации по написанию условий

Рассмотрим пошагово, как составлять эффективные условия в запросах 1С:

  1. Используйте параметры виртуальных таблиц: Если вы работаете с регистрами, всегда выносите период в параметры виртуальной таблицы &НачалоПериода, &КонецПериода. Это отсекает данные на самом раннем этапе.
  2. Соблюдайте чистоту индексируемых полей: Не используйте функции (НАЧАЛОПЕРИОДА, ГОД, ПРЕДСТАВЛЕНИЕ) в левой части условия ГДЕ над полями базы данных.
  3. Приоритет селективности: Ставьте условия по дате и конкретным ссылкам выше, чем фильтры по статусам и булевым флагам. Это делает код логичным.
  4. Используйте ВЫБРАТЬ ПЕРВЫЕ: Если вам нужно просто проверить факт наличия документа, используйте ВЫБРАТЬ ПЕРВЫЕ 1. В сочетании с правильным индексом по дате СУБД прекратит поиск сразу после нахождения первой записи.

Подведем итог: для СУБД порядок условий в ГДЕ чаще всего не имеет значения из-за работы оптимизатора. Однако для разработчика правильный порядок (от частного к общему, от селективного к массовому) является признаком профессионализма и гарантией того, что запрос будет легче поддерживать и анализировать при поиске узких мест в производительности.

← На главную