Как правильно накладывать условия в запросах 1С для оптимизации производительности?

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

При разработке сложных отчетов или обработок в системе 1С:Предприятие программисты часто сталкиваются с дилеммой: на каком этапе выполнения запроса лучше всего ограничивать выборку данными по конкретной организации или другому ключевому измерению? Рассмотрим ситуацию, когда в запросе участвует несколько десятков таблиц, включая документы и их табличные части. Разберем, почему стратегия «сначала фильтруй, потом соединяй» является стандартом разработки и как это влияет на работу СУБД.

Принцип ранней фильтрации данных

Проанализируем базовый подход к написанию запросов. Представим, что у нас есть информационная база с десятком организаций. По каждой из них накоплены сотни тысяч документов с миллионами строк в табличных частях. Если мы сначала объединим все эти данные во временную таблицу и только в самом конце наложим условие ГДЕ Организация = &Параметр, сервер СУБД будет вынужден переработать колоссальный объем лишней информации.

Выясним причину, по которой это происходит. При выполнении запроса СУБД (будь то MSSQL или PostgreSQL) выделяет ресурсы под промежуточные итоги. Собирая «все данные», мы неоправданно раздуваем базу tempdb, создаем лишнюю нагрузку на дисковую подсистему и оперативную память. Правильным решением будет ограничение выборки по организации на самом первом этапе получения данных из каждой таблицы.

Работа с виртуальными таблицами

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


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура,
    ПродажиОбороты.КоличествоОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты
ГДЕ
    ПродажиОбороты.Организация = &Организация

В этом случае платформа сначала может рассчитать итоги по всем организациям за указанный период, сформировать временный результат и только потом отсечь лишние строки. Правильно накладывать условие непосредственно в параметрах виртуальной таблицы. Разберем исправленный вариант:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура,
    ПродажиОбороты.КоличествоОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Организация = &Организация) КАК ПродажиОбороты

При таком подходе СУБД получает уже отфильтрованные данные, что кратно ускоряет выполнение запроса.

Оптимизация временных таблиц

Посмотрим на ситуацию, когда мы используем временные таблицы (ВТ). В 1С временные таблицы физически записываются в базу данных на сервере. Чем меньше строк попадет в первую же ВТ, тем быстрее будут работать все последующие соединения (JOIN). Проанализируем шаги по оптимизации работы с ВТ:

  1. Минимизация состава данных: При помещении данных во временную таблицу (ПОМЕСТИТЬ) всегда используйте фильтр по организации.
  2. Индексация: Если во временной таблице планируется хранить данные, которые позже будут соединяться с другими таблицами по полю Организация, крайне желательно создать индекс по этому полю.
  3. Управление материализацией: Помните, что использование временной таблицы жестко фиксирует состав данных. Оптимизатор СУБД не всегда может «прокинуть» условие из итогового запроса внутрь уже созданной временной таблицы. Поэтому ручная фильтрация в каждой ВТ — обязательный стандарт.

Порядок соединений и «Ведущая таблица»

При соединении нескольких таблиц (особенно если их количество переваливает за 50, как в сложных зарплатных или производственных отчетах) важно определить «ведущую» таблицу. Это таблица с минимальным количеством записей после наложения всех фильтров. Накладывая условие по организации в самом начале, мы делаем первую временную таблицу идеальным кандидатом на роль ведущей.

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

Влияние RLS и требования SARGability

Рассмотрим, как на производительность влияет механизм ограничения прав на уровне записей (RLS). Если в базе включен RLS по организациям, платформа «1С» автоматически добавляет условия в запрос. Если вы уже ограничили выборку конкретной организацией, запрос RLS отработает максимально быстро. В противном случае механизм RLS может добавить сложные соединения с таблицами прав для всех записей, что приведет к катастрофическому падению скорости.

Также важно соблюдать требование SARGability (Search Argumentable). Это означает, что нельзя использовать функции над полями, по которым накладывается условие. Проанализируем пример неудачного условия:

ГДЕ ПРЕДСТАВЛЕНИЕ(Организация) = "Ромашка" или ГДЕ ВЫРАЗИТЬ(Организация КАК Справочник.Организации).Код = "001"

Такие конструкции заставляют СУБД игнорировать индексы и сканировать все данные целиком (Table Scan). Всегда используйте прямое сравнение ссылок: ГДЕ Организация = &Организация.

Рекомендации для сверхбольших запросов

Если ваш запрос содержит 1000 и более строк, как упоминалось в обсуждении, следуйте следующим правилам:

  1. Разбиение на этапы: Не пытайтесь сделать всё в одном огромном пакете. Разбивайте логику на несколько независимых этапов.
  2. Очистка памяти: Используйте команду УНИЧТОЖИТЬ для временных таблиц, которые больше не нужны в текущем пакете. Это освободит место в tempdb.
  3. Контроль типов: Избегайте соединений по полям составного типа, если это возможно. Лучше сначала выгрузить нужные ссылки во временную таблицу с типизацией через ВЫРАЗИТЬ, а потом уже выполнять соединения.

Подведем итог: стратегия наложения условий «на входе» — это не просто хороший тон, а техническая необходимость для стабильной работы системы. Начинайте фильтрацию с самых первых строк кода запроса, используйте параметры виртуальных таблиц и не забывайте про индексацию временных таблиц по ключевым полям фильтрации.

← На главную