ЗУП 3.1: долгое открытие ряда документов (больничный, отпуск, командировка), начиная с релиза 3.1.6.6 - исправление ошибки с кодом 30161250

Публикация № 851017

Программирование - Ошибки в отраслевых решениях

7
В релизе 3.1.6.6 разработчиками была допущена ошибка, заключающаяся в написании крайне неоптимального запроса к базе данных. Конкретно на моей базе, где учет ведется всего пару месяцев, запрос выполнялся около 10 секунд, что уже напрягало. В данной публикации я укажу на расположение данного запроса и выложу текст нового запроса, опубликованного разработчиками в версии для тестирования 3.1.7.67.

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

Текст процедуры:

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

Данная функция проверяет, выплачивалась ли заработная плата в этом периоде - данные берутся из физических таблиц регистров. Т.к. необходим отбор по некоторым значениям, не являющимся измерениями регистров(вид движения и др.), а следовательно не доступных к отбору в виртуальной таблице оборотов. Если пойти от обратного, данная функция является одной из проверок возможности исправления документов в периоде и вызывается только для определяемого типа "ДокументыИсправляемыеВТекущемПериоде", соответственно если какой-то из этих документов у вас при открытии "подвисает", дело скорее всего в этой функции.

Итак, я обнаружила, что в тестовой версии данная функция оптимизирована, поэтому хочу поделиться с вами этой радостной новостью и самой функцией. Я полагаю, что не все скачивают релиз для тестирования и производят это самое тестирование, поэтому могут и не знать о том, что решение есть. Чего уж там, стыдно признаться, но я сама как-то пропустила эту ошибку в баг трекере :) Написала в техподдержку и они уже мне указали на код ошибки, так что публикация, в частности, для таких невнимательных, как я :) 

Исправленная функция в тестовой версии:

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

Если у Вас включена возможность изменения данного модуля, можно просто заменить текст функции на исправленный. Либо если конфигурация находится на поддержке, можно воспользоваться механизмом расширений.

 

7

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. TrinitronOTV 21.06.18 15:57 Сейчас в теме
Релиз 3.1.7.61 уже стал финальным
milov.aleksey; +1 Ответить
2. Bene_Valete 22.06.18 03:03 Сейчас в теме
(1) В связи с некоторыми сюрпризами последних релизов, я бы не торопилась на него обновляться)
3. dka80 16 22.06.18 08:45 Сейчас в теме
(2) не могу не согласиться ))
4. brake71 4 22.06.18 12:20 Сейчас в теме
Побеждал эту проблему расширением, сам запрос переписывал.
Самое интересное, что исходный запрос работает превосходно, но через какое-то время начинает дико тормозить систему - есть подозрение, что статистика на скуле набирается по нему и скуль начинает выбирает не оптимальный план выполнения.

Пробовал в исходном запросе менять
ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
на ВЫБРАТЬ ПЕРВЫЕ 1
| Организация

после чего запрос отрабатывал молниеносно, с учетом того, что больше никаких изменений не вносилось. Но по прошествии часа/получаса история повторялась
7. Bene_Valete 25.06.18 04:55 Сейчас в теме
(4) Особенно интересно искать проблему, когда она то есть - то нет)
5. user911756 22.06.18 12:47 Сейчас в теме
Партнерский пока молчит об ошибках релиза 3.1.7.61
6. Bene_Valete 25.06.18 03:10 Сейчас в теме
(5) У меня нет доступа к партнерскому, если в этом релизе нет ни одной ошибки, которая немного заставит кого-то понервничать - замечательно)
8. user911756 25.06.18 11:59 Сейчас в теме
Лето. Критических изменений нет.
народ спит и не обновился на 3.1.7.61
milov.aleksey; +1 Ответить
9. Bene_Valete 25.06.18 12:06 Сейчас в теме
(8)
Лето. Критических изменений нет
Звучит обнадеживающе, сразу захотелось проснуться и обновится непонятно зачем
10. milov.aleksey 305 27.06.18 11:25 Сейчас в теме
(9) не надо обновляться лишний раз, когда нет веской причины. Иначе лето испортите себе и другим!
11. Bene_Valete 27.06.18 11:43 Сейчас в теме
(10) Полностью согласна, выше был сарказм)) В перечне изменений нового релиза нет ничего такого, что требовало бы тут же на него обновиться, в перечне исправленных ошибок нет тех, которые у нас проявляются. Для франчайзи это может и в порядке вещей, тут же обновится когда релиз вышел(тем более если есть возможность мониторинга ошибок на партнерском форуме), либо для фирмы где работает 10 человек и риски минимальны. А мне этих "своевременных" обновлений достаточно.
Моя публикация так же для тех, для кого обновление на косячный релиз чревато серьезными последствиями, и кстати опубликована она была еще в момент, когда релиз был еще тестовым)
12. Mogilnikova 40 17.01.19 16:18 Сейчас в теме
Я бы рассмотрела вариант с использованием "Различные". Мне в целом не нравится вызывать таблицу накоплений в условии, но так работает быстрее и с другими результатами - У нас в документах "Перенос данных ВЗ" может одновременно быть несколько видов взаиморасчетов и использовать конструкцию "первые 1" крайне неправильно
"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА КАК ЗарегистрированаВыплаченнаяЗарплатаЗаПериод
	|ИЗ
	|	РегистрНакопления.ЗарплатаКВыплате КАК ЗарплатаКВыплате
	|ГДЕ
	|	ЗарплатаКВыплате.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
	|	И ЗарплатаКВыплате.Организация = &Организация
	|	И ЗарплатаКВыплате.ПериодВзаиморасчетов = &ПериодВзаиморасчетов
	|	И ЗНАЧЕНИЕ(Перечисление.ВидыВзаиморасчетовССотрудниками.ВыплатаЗарплаты) В
	|			(ВЫБРАТЬ РАЗЛИЧНЫЕ//ПЕРВЫЕ 1
	|				ВзаиморасчетыССотрудниками.ВидВзаиморасчетов
	|			ИЗ
	|				РегистрНакопления.ВзаиморасчетыССотрудниками КАК ВзаиморасчетыССотрудниками
	|			ГДЕ
	|				ВзаиморасчетыССотрудниками.Регистратор = ЗарплатаКВыплате.Регистратор
	|				И ВзаиморасчетыССотрудниками.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход))"
Показать
Bene_Valete; +1 Ответить
Оставьте свое сообщение