В одном из обновлений от 1С доработан модуль заполнения документа Формирование записей книги продаж после чего время ожидания стало неприлично долгим. Замер производительности показал 1063,478002 (это 17 минут) - после оптимизации кода 66,239374 (1 минута).
Проблема в процедуре модуля документа РаспределитьОплатыПоДеревуСФ(). Тут в цикле создается таблица значений с помощью ПостроителяЗапроса - это результат отбора строк. Для оптимизации достаточно заменить несколько строк кода.
После внесения правок можно использовать типовой алгоритм заполнения - для этого достаточно в комментарий документа написать " [ТиповойАлгоритмЗаполнения] " и сохранить его.
Платформа 1С 8.2, MSSQL.
Надеюсь эта маленькая правка кому-нибудь сэкономит время! :)
// Процедура вызывается из тела процедуры "ЗаполнитьРазделРеализация".
// В процессе работы процедуры общая сумма НДС, которая может быть признана
// в качестве вычета распределяется по конкретным событиям оплаты, для того
// чтобы сопоставить факт признания вычета по НДС и факт оплаты поставщику, связанный
// с этим признанием.
Процедура РаспределитьОплатыПоДеревуСФ(Дерево_НДСНачисленный, ТаблицаРезультатов, СписокСчетовФактур, РаспределенныеОплаты, ОтражатьВРеестре = Истина, ОтражатьВидНачисления = Ложь )
НДСНалоговыйПериод = Неопределено;
Построитель_РаспределенныеОплаты = Новый построительЗапроса();
Построитель_РаспределенныеОплаты.ИсточникДанных = Новый ОписаниеИсточникаДанных(РаспределенныеОплаты);
// Подготовка структуры отбора
Отбор = Построитель_РаспределенныеОплаты.Отбор;
Отбор.Добавить("СчетФактура");
Отбор.СчетФактура.Использование = Истина;
Отбор.Добавить("РаспределеннаяОплата");
Отбор.РаспределеннаяОплата.ВидСравнения = ВидСравнения.Больше;
Отбор.РаспределеннаяОплата.Значение = 0;
Отбор.РаспределеннаяОплата.Использование = Истина;
Построитель_РаспределенныеОплаты.Порядок.Добавить("ДатаОплаты");
ТаблицаОплат = Новый ТаблицаЗначений();
ТаблицаОплат.Колонки.Добавить("ДокументОплаты");
ТаблицаОплат.Колонки.Добавить("ДатаОплаты",Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));
ТаблицаОплат.Колонки.Добавить("СуммаОплаты",Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15,2)));
ТаблицаИсточникаПостроителя = Построитель_РаспределенныеОплаты.ИсточникДанных.ИсточникДанных;
МоментОпределения_ПоОтгрузке = Перечисления.МоментыОпределенияНалоговойБазыНДС.ПоОтгрузке;
//[+] -> ДОБАВЛЯЕМ СВОИ ПЕРЕМЕННЫЕ
ВремТаблицаИсточникаПостроителя = ТаблицаИсточникаПостроителя.СкопироватьКолонки();
ИспользоватьТиповойАлгоритм = (СтрЧислоВхождений(Ссылка.Комментарий, "[ТиповойАлгоритмЗаполнения]") > 0);
//[+] <-
Для каждого СтрокаСФ Из Дерево_НДСНачисленный.Строки Цикл
ТаблицаОплат.Очистить();
Если УчетНДС.ДляСчетаФактурыНеТребуетсяОплата(СтрокаСФ.СчетФактура) Тогда
НаличиеОплатыНеТребуется = Истина;
Иначе
НаличиеОплатыНеТребуется = (СтрокаСФ.Строки[0].МоментОпределенияНалоговойБазыНДС = МоментОпределения_ПоОтгрузке) Или Дата >= '20080101';
//[*] -> МЕНЯЕМ ТИПОВОЙ АЛГОРИТМ...
//Отбор = Построитель_РаспределенныеОплаты.Отбор;
//Отбор.СчетФактура.Значение = СтрокаСФ.СчетФактура;
//Отбор.РаспределеннаяОплата.ВидСравнения = ?(СтрокаСФ.СуммаСНДС>0,ВидСравнения.Больше,ВидСравнения.Меньше);
//
//Построитель_РаспределенныеОплаты.Выполнить();
//Если Построитель_РаспределенныеОплаты.Результат.Пустой() и не НаличиеОплатыНеТребуется и СтрокаСФ.СуммаСНДС >= 0 Тогда
// // Оплата не обнаружена
// Продолжить;
//КонецЕсли;
//
//ВыборкаОплат = Построитель_РаспределенныеОплаты.Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой);
//...С СОХРАНЕНИЕМ ФУНКЦИОНАЛЬНОСТИ ТИПОВОГО ЗАПОЛНЕНИЯ
//
Если ИспользоватьТиповойАлгоритм Тогда
Отбор = Построитель_РаспределенныеОплаты.Отбор;
Отбор.СчетФактура.Значение = СтрокаСФ.СчетФактура;
Отбор.РаспределеннаяОплата.ВидСравнения = ?(СтрокаСФ.СуммаСНДС>0,ВидСравнения.Больше,ВидСравнения.Меньше);
Построитель_РаспределенныеОплаты.Выполнить();
Если Построитель_РаспределенныеОплаты.Результат.Пустой() и не НаличиеОплатыНеТребуется и СтрокаСФ.СуммаСНДС >= 0 Тогда
// Оплата не обнаружена
Продолжить;
КонецЕсли;
ВыборкаОплат = Построитель_РаспределенныеОплаты.Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой);
Иначе
ПоискОтбор = Новый Структура();
ПоискОтбор.Вставить("СчетФактура", СтрокаСФ.СчетФактура);
ПоискОплат = ТаблицаИсточникаПостроителя.НайтиСтроки(ПоискОтбор);
ВыборкаОплат = ВремТаблицаИсточникаПостроителя.Скопировать();
Если ПоискОплат.Количество() > 0 Тогда
Для каждого СтрокаПоиска Из ПоискОплат Цикл
Если СтрокаСФ.СуммаСНДС > 0 Тогда
Если СтрокаПоиска.РаспределеннаяОплата > 0 Тогда
СтрокаВыборки = ВыборкаОплат.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаВыборки, СтрокаПоиска);
КонецЕсли;
Иначе
Если СтрокаПоиска.РаспределеннаяОплата < 0 Тогда
СтрокаВыборки = ВыборкаОплат.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаВыборки, СтрокаПоиска);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ВыборкаОплат.Количество() = 0 Тогда
Если (НЕ НаличиеОплатыНеТребуется И СтрокаСФ.СуммаСНДС >= 0) Тогда
// Оплата не обнаружена
Продолжить;
КонецЕсли;
КонецЕсли;
КонецЕсли;
//[*] <-
СуммаКПогашению = СтрокаСФ.СуммаСНДС;
Для каждого СтрокаРаспределеннойОплаты Из ВыборкаОплат Цикл
/// ....
РаспределенныеОплаты = ТаблицаИсточникаПостроителя.Скопировать();
КонецПроцедуры // РаспределитьОплатыПоДеревуСФ()
P.S.: ну а дальше запросы, но это уже совсем другая история...