ЗУП 3.1: долгое открытие ряда документов (больничный, отпуск, командировка), начиная с релиза 3.1.6.6 — исправление ошибки с кодом 30161250
В релизе 3.1.6.6 разработчиками была допущена ошибка, заключающаяся в написании крайне неоптимального запроса к базе данных. Конкретно на моей базе, где учет ведется всего пару месяцев, запрос выполнялся около 10 секунд, что уже напрягало. В данной публикации я укажу на расположение данного запроса и выложу текст нового запроса, опубликованного разработчиками в версии для тестирования 3.1.7.67.
- Описание
- Подробнее
Описание
Доброго времени суток! Заранее прошу прощения, если подобный материал уже есть здесь.
Наверняка многие из вас заметили, что, начиная с релиза 3.1.6.6 ряд документов стал открываться подозрительно долго. К примеру, документ "Больничный" мог открываться по 10 секунд и больше. При помощи замера производительности было выяснено, что проблема кроется в функции "ПроизводиласьВыплатаЗарплатыПоПериодуВзаиморасчетов" общего модуля ВзаиморасчетыССотрудникамиРасширенный:

Текст процедуры:
// Проверяет, регистрировалась ли во взаиморасчетах выплата зарплаты за указанный период.
//
// Параметры:
// Организация - СправочникСсылка.Организация - организация, в которой проверяется наличие выплат.
// ПериодВзаиморасчетов - Дата - Период, за который требуется проверить выплату зарплаты.
//
// Возвращаемое значение:
// Булево - Истина, если за период взаиморасчетов выплачивалась зарплата, иначе Ложь.
//
Функция ЗарегистрированаВыплаченнаяЗарплатаЗаПериод(Организация, ПериодВзаиморасчетов) Экспорт
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("ПериодВзаиморасчетов", НачалоМесяца(ПериодВзаиморасчетов));
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК ЗарегистрированаВыплаченнаяЗарплатаЗаПериод
|ИЗ
| РегистрНакопления.ЗарплатаКВыплате КАК ЗарплатаКВыплате
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ВзаиморасчетыССотрудниками КАК ВзаиморасчетыССотрудниками
| ПО (ВзаиморасчетыССотрудниками.Регистратор = ЗарплатаКВыплате.Регистратор)
|ГДЕ
| ЗарплатаКВыплате.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| И ЗарплатаКВыплате.Организация = &Организация
| И ЗарплатаКВыплате.ПериодВзаиморасчетов = &ПериодВзаиморасчетов
| И ВзаиморасчетыССотрудниками.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| И ВзаиморасчетыССотрудниками.ВидВзаиморасчетов = ЗНАЧЕНИЕ(Перечисление.ВидыВзаиморасчетовССотрудниками.ВыплатаЗарплаты)";
РезультатЗапроса = Запрос.Выполнить();
Возврат НЕ РезультатЗапроса.Пустой();
КонецФункцииДанная функция проверяет, выплачивалась ли заработная плата в этом периоде — данные берутся из физических таблиц регистров. Т.к. необходим отбор по некоторым значениям, не являющимся измерениями регистров(вид движения и др.), а следовательно не доступных к отбору в виртуальной таблице оборотов. Если пойти от обратного, данная функция является одной из проверок возможности исправления документов в периоде и вызывается только для определяемого типа "ДокументыИсправляемыеВТекущемПериоде", соответственно если какой-то из этих документов у вас при открытии "подвисает", дело скорее всего в этой функции.

Итак, я обнаружила, что в тестовой версии данная функция оптимизирована, поэтому хочу поделиться с вами этой радостной новостью и самой функцией. Я полагаю, что не все скачивают релиз для тестирования и производят это самое тестирование, поэтому могут и не знать о том, что решение есть. Чего уж там, стыдно признаться, но я сама как-то пропустила эту ошибку в баг трекере 🙂 Написала в техподдержку и они уже мне указали на код ошибки, так что публикация, в частности, для таких невнимательных, как я 🙂
Исправленная функция в тестовой версии:
// Проверяет, регистрировалась ли во взаиморасчетах выплата зарплаты за указанный период.
//
// Параметры:
// Организация - СправочникСсылка.Организация - организация, в которой проверяется наличие выплат.
// ПериодВзаиморасчетов - Дата - Период, за который требуется проверить выплату зарплаты.
//
// Возвращаемое значение:
// Булево - Истина, если за период взаиморасчетов выплачивалась зарплата, иначе Ложь.
//
Функция ЗарегистрированаВыплаченнаяЗарплатаЗаПериод(Организация, ПериодВзаиморасчетов) Экспорт
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("ПериодВзаиморасчетов", НачалоМесяца(ПериодВзаиморасчетов));
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК ЗарегистрированаВыплаченнаяЗарплатаЗаПериод
|ИЗ
| РегистрНакопления.ЗарплатаКВыплате КАК ЗарплатаКВыплате
|ГДЕ
| ЗарплатаКВыплате.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
| И ЗарплатаКВыплате.Организация = &Организация
| И ЗарплатаКВыплате.ПериодВзаиморасчетов = &ПериодВзаиморасчетов
| И ЗНАЧЕНИЕ(Перечисление.ВидыВзаиморасчетовССотрудниками.ВыплатаЗарплаты) В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ВзаиморасчетыССотрудниками.ВидВзаиморасчетов
| ИЗ
| РегистрНакопления.ВзаиморасчетыССотрудниками КАК ВзаиморасчетыССотрудниками
| ГДЕ
| ВзаиморасчетыССотрудниками.Регистратор = ЗарплатаКВыплате.Регистратор
| И ВзаиморасчетыССотрудниками.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход))";
УстановитьПривилегированныйРежим(Истина);
РезультатЗапроса = Запрос.Выполнить();
УстановитьПривилегированныйРежим(Ложь);
Возврат НЕ РезультатЗапроса.Пустой();
КонецФункции
Если у Вас включена возможность изменения данного модуля, можно просто заменить текст функции на исправленный. Либо если конфигурация находится на поддержке, можно воспользоваться механизмом расширений.

