При разработке сложных отчетов или обработок в системе 1С:Предприятие программисты часто сталкиваются с дилеммой: на каком этапе выполнения запроса лучше всего ограничивать выборку данными по конкретной организации или другому ключевому измерению? Рассмотрим ситуацию, когда в запросе участвует несколько десятков таблиц, включая документы и их табличные части. Разберем, почему стратегия «сначала фильтруй, потом соединяй» является стандартом разработки и как это влияет на работу СУБД.
Проанализируем базовый подход к написанию запросов. Представим, что у нас есть информационная база с десятком организаций. По каждой из них накоплены сотни тысяч документов с миллионами строк в табличных частях. Если мы сначала объединим все эти данные во временную таблицу и только в самом конце наложим условие ГДЕ Организация = &Параметр, сервер СУБД будет вынужден переработать колоссальный объем лишней информации.
Выясним причину, по которой это происходит. При выполнении запроса СУБД (будь то MSSQL или PostgreSQL) выделяет ресурсы под промежуточные итоги. Собирая «все данные», мы неоправданно раздуваем базу tempdb, создаем лишнюю нагрузку на дисковую подсистему и оперативную память. Правильным решением будет ограничение выборки по организации на самом первом этапе получения данных из каждой таблицы.
Особое внимание уделим работе с виртуальными таблицами, такими как Остатки, Обороты или СрезПоследних. Рассмотрим пример типичной ошибки, когда условие накладывается в секции ГДЕ:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты
ГДЕ
ПродажиОбороты.Организация = &Организация
В этом случае платформа сначала может рассчитать итоги по всем организациям за указанный период, сформировать временный результат и только потом отсечь лишние строки. Правильно накладывать условие непосредственно в параметрах виртуальной таблицы. Разберем исправленный вариант:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Организация = &Организация) КАК ПродажиОбороты
При таком подходе СУБД получает уже отфильтрованные данные, что кратно ускоряет выполнение запроса.
Посмотрим на ситуацию, когда мы используем временные таблицы (ВТ). В 1С временные таблицы физически записываются в базу данных на сервере. Чем меньше строк попадет в первую же ВТ, тем быстрее будут работать все последующие соединения (JOIN). Проанализируем шаги по оптимизации работы с ВТ:
ПОМЕСТИТЬ) всегда используйте фильтр по организации.Организация, крайне желательно создать индекс по этому полю.При соединении нескольких таблиц (особенно если их количество переваливает за 50, как в сложных зарплатных или производственных отчетах) важно определить «ведущую» таблицу. Это таблица с минимальным количеством записей после наложения всех фильтров. Накладывая условие по организации в самом начале, мы делаем первую временную таблицу идеальным кандидатом на роль ведущей.
СУБД будет проще построить эффективный план выполнения, используя эту маленькую выборку для быстрого поиска по индексам в огромных таблицах документов через механизм Nested Loops (вложенные циклы).
Рассмотрим, как на производительность влияет механизм ограничения прав на уровне записей (RLS). Если в базе включен RLS по организациям, платформа «1С» автоматически добавляет условия в запрос. Если вы уже ограничили выборку конкретной организацией, запрос RLS отработает максимально быстро. В противном случае механизм RLS может добавить сложные соединения с таблицами прав для всех записей, что приведет к катастрофическому падению скорости.
Также важно соблюдать требование SARGability (Search Argumentable). Это означает, что нельзя использовать функции над полями, по которым накладывается условие. Проанализируем пример неудачного условия:
ГДЕ ПРЕДСТАВЛЕНИЕ(Организация) = "Ромашка" или ГДЕ ВЫРАЗИТЬ(Организация КАК Справочник.Организации).Код = "001"
Такие конструкции заставляют СУБД игнорировать индексы и сканировать все данные целиком (Table Scan). Всегда используйте прямое сравнение ссылок: ГДЕ Организация = &Организация.
Если ваш запрос содержит 1000 и более строк, как упоминалось в обсуждении, следуйте следующим правилам:
УНИЧТОЖИТЬ для временных таблиц, которые больше не нужны в текущем пакете. Это освободит место в tempdb.ВЫРАЗИТЬ, а потом уже выполнять соединения.Подведем итог: стратегия наложения условий «на входе» — это не просто хороший тон, а техническая необходимость для стабильной работы системы. Начинайте фильтрацию с самых первых строк кода запроса, используйте параметры виртуальных таблиц и не забывайте про индексацию временных таблиц по ключевым полям фильтрации.