Оптимизация проведения документов списания партий в УПП 1.3

09.09.21

База данных - HighLoad оптимизация

Почти в каждой конфигурации УПП 1.3 (возможно, и в УТ 10.3) есть медленный запрос, тормозящий проведение документа списания. Данная публикация раскрывает места вызова данного запроса и приводит пример оптимизации. Пример показывает результаты проведения документа «Реализация товаров и услуг», но метод работает и для других документов списания партий.

Примерно, в 2019 году я отлаживал некоторую разработку в УТ 10.3.15.9, в ходе которой проводил документ «Реализация товаров и услуг» (РТУ). После многочисленных проведений и я обнаружил, что иногда при проведении происходит длительное зависание (минута-две), когда обычно РТУ проводится в течение 10 секунд. В конфигураторе замер производительности показал топовую строку кода:

 

УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(Ссылка, Движения.СписанныеТовары.Выгрузить(),,,,,,,,,,Отказ);

Другие детали конфигуратор скрыл, на тот момент у меня отсутствовал доступ к технологическому журналу (ТЖ), к СУБД тоже отсутствовал (хотя было известно, что это MS SQL Server 2008 R2), и задача была другая, поэтому дальнейшее расследование остановлено.

Прошло время (2018, 2019, 2020), и вот в 2021 году поступила задача: в системе УПП 1.3.162 медленно проводится реализация.

Для начала проверен программный код, и обнаружена следующая конструкция:

 

 

 

 

Что мы наблюдаем: в модуле РТУ создается COM-соединение с базой MySQL (которая может оказаться достаточно далеко, и связь с которой может оказаться достаточно медленной и с прерываниями), выполняется команда в базе MySQL(которая тоже может быть длительной), и все это выполняется два раза: в процедурах ПередЗаписью, ОбработкаПроведения.

Очевидно, что данный функционал следует перестроить архитектурно, что в первую очередь и сделано:

1) создан регистр сведений «Документы интеграции», в который записывается информация при проведении РТУ;

2) создано регламентное задание, которое соединяется с базой MySQL и выполняет необходимые команды.

Данное изменение перестало мешать и оказалось полезным для разгрузки времени проведения, но не было основной причиной.

На этот раз доступ к ТЖ был, собраны события: CALL, SCALL, DBMSSQL, EXCP.

ТЖ показал:

 
 CALL
 
 DBMSSQL

 

То есть тормоза находятся в общем модуле УправлениеЗапасамиПартионныйУчет.

Конечная строка: Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

Из данных строк ТЖ получаем, что на СУБД внезапно запрос выполняется медленно. Но что может вызывать такое непредсказуемое поведение?

Через Extended Events собраны планы запросов (к сожалению, уже не сохранились, приложить нечего), планы генерируются распараллеленными, поиск в таблицах выполняется по индексам, ничего особенно, но как-то медленно происходят соединения таблиц (60-90% времени), причем такие замедления бывают иногда, а часто в основном быстро без задержек.

Остается смотреть текст запроса:

 
 Процедура ЗаполнитьЗапросПартийНаСкладахУпр

 

В запросе остатки соединяются несколько раз с регистром СписанныеТовары.

Нужно отметить, что объем данных регистров достаточный:

РегистрНакопления.ПартииТоваровНаСкладах: 4 млн. строк.

РегистрСведений.СписанныеТовары: 3 млн. строк.

РегистрНакопления.ПартииТоваровНаСкладах.Итоги: 100 тыс. строк.

Казалось, что достаточно чаще пересчитывать итоги, и всегда будет использоваться только 100 тыс. строк, то есть только итоги вместо основного регистра, но функциональная специфика работы организации такова, что старые периоды редактируют почти каждый день много раз, поэтому в запросе используется именно основной регистр с 4 млн. строк.

И вот мы представляем, как 4 млн. строк соединяются с 3 млн. строк несколько раз, пусть даже по индексам, но поиск по таким объемам уже дает о себе знать, и похоже в этом и причина.

И тогда я задался мыслью: а зачем каждый раз обращаться в регистр СписанныеТовары, если товаров всего пару десятков для РТУ и их можно получить всего один раз для дальнейшего использования! И такая временная таблица уже даже присутствует в программном коде — это переменная ТаблицаСписания, которую достаточно передать в запрос в качестве параметра.

 

 

И теперь можно перестроить запрос с использованием существующей таблицы, избавившись от многоразового подтягивания многомилионного регистра СписанныеТовары.

 
 Процедура КС_ЗаполнитьЗапросПартийНаСкладахУпр_РТУ

 

Нужно еще отметить: так как данная оптимизация значительно затрагивает функционал, повышает риск сбоев в остатках, то пришлось потратить некоторое время на проверку после массового проведения документов. Сверяли остатки двух баз: остатки до с остатками после оптимизации.

 

Итог

За день проводится около 200 РТУ.

Результаты до оптимизации: каждая пятая РТУ проводилась около минуты-полторы, каждая третья РТУ проводилась около 15-30 секунд.

Результат после оптимизации: за день около 2-3 РТУ проводится в течение 20 секунд, остальные проводятся менее 10 секунд.

Результаты проведения других документов не проверял, но суть та же.

Вступайте в нашу телеграмм-группу Инфостарт

УПП 1.3 оптимизация проведение реализации списание партий ускорение проведения списания запросов

См. также

HighLoad оптимизация Программист 1С 8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    6667    ivanov660    48    

52

HighLoad оптимизация Программист 1С:Предприятие 8 1C:ERP Бесплатно (free)

Приведем примеры использования различных в динамических списках и посмотрим, почему это плохо.

18.02.2025    9031    ivanov660    39    

61

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    11474    ivanov660    13    

64

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    17825    Evg-Lylyk    73    

46

HighLoad оптимизация Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    8738    spyke    29    

54

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    12140    vasilev2015    22    

47
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. 1c-intelligence 13101 10.09.21 07:43 Сейчас в теме
А можно:
1. Выполнять списание партий фоновым заданием, вне транзакции проведения документа;
2. Не списывать партии при проведении документа, делать это регл. заданием;
3. Перейти на РАУЗ;
4. Свернуть базу.
3. info1i 246 10.09.21 09:54 Сейчас в теме
(1) 1,2. Можно, но требует более дорогого продумывания, не всегда это возможно, много касс списывают с одного склада товар, скоростная конкуренция за актуальные остатки высокая, требует переобучения пользователей (хочется ведь видеть сразу результат проведения, а не когда закончится фоновое).
3,4. Дорого, порой даже значительно дороже текущего решения. И заказчик не готов резать свою базу на части, чтобы потом смотреть ее в разных местах.
2. MiniGrad2014 10.09.21 08:32 Сейчас в теме
Не знаете, в УТ 10-ой может быть что-то подобное?
4. info1i 246 10.09.21 09:56 Сейчас в теме
(2) Да, может - это то, с чего началась история. Ориентируйтесь на указанные мной строчки кода и найдите текст запроса, который получает партии перед списанием.
5. kauksi 217 09.12.21 10:48 Сейчас в теме
Очевидно что это какая то специфичная УПП с встроенным бит-Финансом, поэтому это косяк разработчиков БФ
6. wolder 133 02.08.23 05:41 Сейчас в теме
А что за функция : ПараметрыЗапроса_ДатаОприходования = ПолучитьДанныеДляЗапроса_ДокументОприходованияДата(СпособОценкиМПЗ,"ПартииТоваровНаСкладах");

Возвращает структуру? В Ут 10.3 её нет. Судя по синтаксису это не родная функция от конфигурации.
Можете её выложить?
7. info1i 246 02.08.23 23:33 Сейчас в теме
(6)
Функция ПолучитьДанныеДляЗапроса_ДокументОприходованияДата(СпособОценкиМПЗ, ПсевдонимТаблицы)
	флПоСредней = ложь;
	Если ТипЗнч(СпособОценкиМПЗ)=Тип("Строка") И ВРег(СпособОценкиМПЗ) = "ПО СРЕДНЕЙ" Тогда
		флПоСредней = истина;
	КонецЕсли;
	Если флПоСредней Тогда
		стрПолеВыборки 		= "";
		стрПолеСортировки 	= "";
	Иначе
		стрПолеВыборки 		= ПсевдонимТаблицы+".ДокументОприходования.Дата КАК ДокументОприходованияДата,";
		стрПолеСортировки 	= "ДокументОприходованияДата"+ ?(СпособОценкиМПЗ = "ЛИФО", " Убыв","") + ",";
	КонецЕсли;
	Возврат новый Структура("ДокОприходованияДата_Выбор,ДокОприходованияДата_Сортировка",стрПолеВыборки,стрПолеСортировки);
КонецФункции
Показать
Для отправки сообщения требуется регистрация/авторизация