При сверке данных между двумя информационными базами нередко приходится сопоставлять документы по дополнительным реквизитам или свойствам. Однако сложные запросы к виртуальным таблицам регистров бухгалтерии с множеством соединений могут выполняться крайне медленно — вплоть до нескольких часов. Разберем основные причины падения производительности и выясним, как правильно переписать такой запрос для многократного ускорения.
Проанализируем типичный проблемный запрос и выделим критические ошибки, приводящие к деградации производительности:
ТиповойОбороты.Регистратор.Дата или Сторнирование.ДокументОснование.Дата заставляет платформу 1С формировать в СУБД левые соединения со всеми таблицами документов, входящими в составной тип Регистратор или ДокументОснование. Если в типе десятки документов, план запроса превращается в громоздкое дерево соединений.ОборотыВсе.Субконто1.Наименование, ОборотыВсе.Субконто2.ajs_id) порождает соединения со всеми типами объектов, включенными в план видов характеристик ВидыСубконтоХозрасчетные.Значение регистра сведений ЗначенияСвойствОбъектов имеет составной тип. Использование его в выражении МЕЖДУ &Дата1 И &Дата2 или внутри функции ЕСТЬNULL без приведения типа приводит к неявному преобразованию типов на стороне СУБД, что исключает использование индексов и вызывает полное сканирование таблицы (Index Scan / Table Scan).РегистрБухгалтерии.Типовой.Обороты(&Дата1, , ...), платформа считывает все записи с начальной даты до бесконечности, а затем фильтрует их во внешнем блоке ГДЕ.ГДЕ лишает виртуальную таблицу возможности применить штатные кластерные индексы по периоду и счету.Рассмотрим, как устранить неявные соединения. Если известно, к какому именно типу относится ссылка или значение свойства, необходимо явно указать его с помощью функции ВЫРАЗИТЬ.
Посмотрим на пример приведения типа для регистратора и документа-основания:
ВЫБРАТЬ
ВЫРАЗИТЬ(ТиповойОбороты.Регистратор КАК Документ.Сторнирование).ДокументОснование КАК ДокументОснование
ИЗ
РегистрБухгалтерии.Типовой.Обороты(&Дата1, &Дата2, Регистратор, Счет = &Счет, , Организация = &Организация, , ) КАК ТиповойОбороты
Аналогично поступим с полями субконто при получении их реквизитов. Если Субконто1 гарантированно является справочником контрагентов, приведем его к нужному типу:
ВЫБРАТЬ
ВЫРАЗИТЬ(Обороты.Субконто1 КАК Справочник.Контрагенты).Наименование КАК КонтрагентНаименование,
ВЫРАЗИТЬ(Обороты.Субконто1 КАК Справочник.Контрагенты).ИдентификационныйКодЛичности КАК БИН,
ВЫРАЗИТЬ(Обороты.Субконто2 КАК Справочник.ДоговорыКонтрагентов).ajs_id КАК ajs_id
ИЗ
Обороты КАК Обороты
Для поля Значение регистра сведений ЗначенияСвойствОбъектов также обязательно задаем тип:
ВЫРАЗИТЬ(ЗначенияСвойствОбъектовДатаББ.Значение КАК ДАТА)
В большинстве конфигураций 1С проводки и движения документов формируются на дату самого документа. В виртуальной таблице оборотов с периодичностью Регистратор доступно стандартное поле Период.
Замена конструкции ТиповойОбороты.Регистратор.Дата на ТиповойОбороты.Период позволяет получить дату движения без разыменования ссылки и без дополнительных соединений к таблицам документов.
Разберем по шагам наиболее эффективный архитектурный подход. Вместо объединения тяжелых таблиц в одном запросе разобьем задачу на этапы с использованием временных таблиц.
Посмотрим на пример реализации:
// 1. Собираем документы с учетом даты свойства
ВЫБРАТЬ
Свойства.Объект КАК Ссылка,
ВЫРАЗИТЬ(Свойства.Значение КАК ДАТА) КАК РеальнаяДата
ПОМЕСТИТЬ ВТ_ДатыСвойств
ИЗ
РегистрСведений.ЗначенияСвойствОбъектов КАК Свойства
ГДЕ
Свойства.Свойство = &СвойствоДатаББ
И ВЫРАЗИТЬ(Свойства.Значение КАК ДАТА) МЕЖДУ &Дата1 И &Дата2
ИНДЕКСИРОВАТЬ ПО
Ссылка
;
// 2. Получаем обороты и связываем их с подготовленными данными
ВЫБРАТЬ
Движения.Счет КАК Счет,
Движения.Организация КАК Организация,
Движения.Субконто1 КАК Субконто1,
Движения.Субконто2 КАК Субконто2,
Движения.Сумма КАК Сумма
ПОМЕСТИТЬ ВТ_Обороты
ИЗ
РегистрБухгалтерии.Типовой.ДвиженияССубконто(&Дата1, &Дата2, Счет = &Счет И Организация = &Организация) КАК Движения
ГДЕ
Движения.Регистратор В (ВЫБРАТЬ ВТ_ДатыСвойств.Ссылка ИЗ ВТ_ДатыСвойств)
;
// 3. Выбираем и группируем итоговые данные с явным приведением типов
ВЫБРАТЬ
ВЫРАЗИТЬ(ВТ_Обороты.Субконто1 КАК Справочник.Контрагенты).Наименование КАК Контрагент,
ВЫРАЗИТЬ(ВТ_Обороты.Субконто2 КАК Справочник.ДоговорыКонтрагентов).Наименование КАК Договор,
СУММА(ВТ_Обороты.Сумма) КАК Сумма
ИЗ
ВТ_Обороты КАК ВТ_Обороты
СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(ВТ_Обороты.Субконто1 КАК Справочник.Контрагенты).Наименование,
ВЫРАЗИТЬ(ВТ_Обороты.Субконто2 КАК Справочник.ДоговорыКонтрагентов).Наименование
Виртуальная таблица Обороты с периодичностью Регистратор фактически выполняет группировку записей регистра бухгалтерии. Если требуется детализация до каждого регистратора и субконто, эффективнее обращаться напрямую к физической таблице РегистрБухгалтерии.Типовой.ДвиженияССубконто (или основной таблице регистра бухгалтерии), фильтруя записи по счету, периоду и организации.
Важные правила при оптимизации запросов к регистрам:
НачалоПериода и КонецПериода) в виртуальные таблицы.ИНДЕКСИРОВАТЬ ПО для полей временных таблиц, которые участвуют в соединениях и условиях В / ГДЕ.ВЫРАЗИТЬ.