Существует распространенное правило оптимизации запросов в платформе 1С:Предприятие 8.3 — все отборы по измерениям и периодам необходимо передавать напрямую в параметры виртуальных таблиц, а не оставлять в секции ГДЕ. Однако на практике слепое следование этому правилу может не ускорить, а существенно замедлить выполнение запроса (вплоть до нескольких раз), особенно в файловых базах данных (1CD) и при работе с периодическими регистрами сведений. Разберем детально, почему это происходит и как правильно оптимизировать запросы.
Проанализируем две принципиально разные конструкции запроса к регистру сведений. В исходном варианте запрос обращался напрямую к физической таблице регистра:
ВЫБРАТЬ
План.Клуб КАК Клуб,
План.Вид КАК Вид,
План.Сумма КАК Сумма,
План.Период КАК Период
ИЗ
РегистрСведений.План КАК План
ГДЕ
План.Период >= &ВыбНач И План.Период <= &ВыбКон
И План.Клуб = &ВыбКлуб
И План.Вид В ИЕРАРХИИ(&ВыбВид)
После попытки «оптимизации» запрос был переписан на обращение к виртуальной таблице СрезПоследних:
ВЫБРАТЬ
План.Клуб КАК Клуб,
План.Вид КАК Вид,
План.Сумма КАК Сумма,
План.Период КАК Период
ИЗ
РегистрСведений.План.СрезПоследних(&ВыбКон, Клуб = &Клуб И Вид В ИЕРАРХИИ(&ВыбВид)) КАК План
Рассмотрим, что произошло на уровне СУБД:
СрезПоследних на произвольную дату физически не хранится в базе в готовом виде. Платформа 1С динамически генерирует сложный подзапрос с группировкой по всем измерениям и поиском максимума даты (MAX(Период)), после чего результат внутренне соединяется с основной таблицей регистра для извлечения ресурсов.Вывод: Если по бизнес-логике требуется получить просто записи регистра за период (например, плановые суммы по месяцам), нельзя использовать СрезПоследних. Для таких задач предназначен прямой запрос к физической таблице регистра с отбором по периоду.
Конструкция В ИЕРАРХИИ при выполнении запроса разворачивается платформой в рекурсивную выборку всех элементов-потомков и передачу их во внутренний запрос через массив IN (...). Если поместить такое условие в параметры виртуальной таблицы СрезПоследних, огромный массив значений встраивается внутрь каждого подзапроса группировки и расчета максимальной даты, что приводит к резкой деградации производительности.
Разберем практические варианты ускорения в зависимости от поставленной задачи.
Если нам нужно выбрать все записи за период с фильтрацией по группе справочника, используем прямое обращение к физической таблице и выносим иерархию во временную таблицу для быстрого соединения по индексу:
ВЫБРАТЬ
Виды.Ссылка КАК Вид
ПОМЕСТИТЬ ВТ_Виды
ИЗ
Справочник.ВидыПланов КАК Виды
ГДЕ
Виды.Ссылка В ИЕРАРХИИ(&ВыбВид)
ИНДЕКСИРОВАТЬ ПО
Вид
;
ВЫБРАТЬ
План.Клуб КАК Клуб,
План.Вид КАК Вид,
План.Сумма КАК Сумма,
План.Период КАК Период
ИЗ
РегистрСведений.План КАК План
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Виды КАК ВТ_Виды
ПО План.Вид = ВТ_Виды.Вид
ГДЕ
План.Период МЕЖДУ &ВыбНач И &ВыбКон
И План.Клуб = &ВыбКлуб
ИТОГИ
СУММА(Сумма)
ПО
ОБЩИЕ
Если бизнес-логика действительно требует получения среза последних записей на дату, оптимизируем запрос пакетом с предварительной выборкой иерархии во временную таблицу:
ВЫБРАТЬ
Виды.Ссылка КАК Вид
ПОМЕСТИТЬ ВТ_НужныеВиды
ИЗ
Справочник.ВидыПланов КАК Виды
ГДЕ
Виды.Ссылка В ИЕРАРХИИ(&ВыбВид)
ИНДЕКСИРОВАТЬ ПО
Вид
;
ВЫБРАТЬ
План.Клуб КАК Клуб,
План.Вид КАК Вид,
План.Сумма КАК Сумма,
План.Период КАК Период
ИЗ
РегистрСведений.План.СрезПоследних(&ВыбКон, Клуб = &Клуб) КАК План
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_НужныеВиды КАК ВТ_НужныеВиды
ПО План.Вид = ВТ_НужныеВиды.Вид
ИТОГИ
СУММА(Сумма)
ПО
ОБЩИЕ
В этом случае в параметрах среза остаются только точные отборы на равенство по проиндексированным измерениям (Клуб = &Клуб), а тяжелое условие иерархии отрабатывает через эффективное внутреннее соединение с проиндексированной временной таблицей.
Для регистров накопления и их виртуальной таблицы Обороты перенос отборов в параметры функции действительно дает прирост скорости, так как платформа обращается к предварительно рассчитанным итогам. Однако важно учитывать следующие правила:
&ВыбНач и &ВыбКон) должны строго соответствовать границам периодичности хранения итогов (например, начало первого дня месяца 00:00:00 и конец последнего дня 23:59:59). При произвольных секундах платформа будет дополнительно считывать физические таблицы движений.