Зависание регламентной операции «Корректировка стоимости номенклатуры» — одна из самых коварных проблем в работе 1С:Предприятие в клиент-серверном варианте. Ситуация часто выглядит одинаково: в файловой базе месяц закрывается за считанные минуты, а на мощном SQL-сервере процесс может длиться часами или вовсе «уходить в бесконечность». В этой статье мы подробно разберем, почему это происходит, и проанализируем пошаговые методы решения проблемы: от простых манипуляций с базой до глубокой оптимизации программного кода.
Проанализируем механику работы операции. Корректировка стоимости — это сложный алгоритм, который пересчитывает себестоимость списания с учетом всех поступлений и перемещений за период. Основная нагрузка ложится на запросы к регистрам бухгалтерии (Хозрасчетный) и накопления (ПартииТоваровНаСкладах). Когда мы сталкиваемся с тем, что в консоли запросов всё работает быстро, а при выполнении кода — виснет, причина чаще всего кроется в неудачном плане запроса, который строит оптимизатор MS SQL Server.
Рассмотрим подробнее основные факторы:
В ИЕРАРХИИ внутри параметров виртуальной таблицы заставляет SQL выполнять тяжелые вложенные сканирования.Прежде чем менять код, попробуем «встряхнуть» SQL-сервер. Часто проблема решается простой очисткой процедурного кэша и обновлением статистик. Если после выгрузки в .dt и обратной загрузки месяц закрывается один раз нормально, а потом снова виснет — это явный признак проблем со статистикой таблиц.
Выполним следующие команды в SQL Management Studio для вашей базы данных:
-- Очистка кэша планов выполнения
DBCC FREEPROCCACHE;
DBCC FREESESSIONCACHE;
DBCC FREESYSTEMCACHE ('ALL');
DBCC DROPCLEANBUFFERS;
GO
-- Обновление статистик с полным сканированием
UPDATE STATISTICS [ИмяТаблицыРегистраБухгалтерии] WITH FULLSCAN;
Разберем, что это дает: эти команды заставляют сервер забыть старые неоптимальные планы и собрать актуальную информацию о распределении данных в таблицах. Это позволяет СУБД построить новый, более быстрый план выполнения запроса.
Если стандартные средства SQL не помогают, перейдем к анализу программного кода. Проанализируем процедуру ПолучитьТаблицуПеремещений или ПолучитьТаблицуОперацийСписания в общем модуле КорректировкаСтоимости. Одной из критических ошибок является использование больших списков счетов с проверкой иерархии прямо в параметрах виртуальной таблицы.
Рассмотрим пример того, как нельзя оставлять запрос:
Запрос.Текст = "ВЫБРАТЬ ...
|ИЗ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&ДатаНач, &ДатаКон, ,
| СчетДт В ИЕРАРХИИ (&СписокСчетов), ,
| СчетКт В ИЕРАРХИИ (&СписокСчетов), , ...) КАК ХозрасчетныйОбороты";
Перепишем этот фрагмент, используя временные таблицы. Это «разгрузит» оптимизатор SQL и позволит ему четко понять объем выборки. Разберем по шагам:
// Сначала подготовим список всех счетов с учетом иерархии
Запрос.Текст = "ВЫБРАТЬ
| Хозрасчетный.Ссылка КАК Ссылка
|ПОМЕСТИТЬ ВТ_Счета
|ИЗ
| ПланСчетов.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Ссылка В ИЕРАРХИИ(&СписокСчетов)
|
|ИНДЕКСИРОВАТЬ ПО
| Ссылка;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ ...
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&ДатаНач, &ДатаКон, ,
| СчетДт В (ВЫБРАТЬ Ссылка ИЗ ВТ_Счета), ,
| СчетКт В (ВЫБРАТЬ Ссылка ИЗ ВТ_Счета), , ...) КАК ХозрасчетныйОбороты";
Такой подход гарантирует, что SQL-сервер сначала определит конкретный список идентификаторов счетов и только потом пойдет искать обороты по ним, что значительно ускоряет выполнение в режиме клиент-сервер.
Иногда зависание вызвано некорректной работой с типами данных в массивах. В некоторых релизах конфигураций была замечена проблема, когда игры с типом NULL приводили к разнице в поведении файловой и серверной баз. Посмотрим на пример исправления в процедуре ОцифроватьСостояния:
// Вместо создания пустого массива с типом NULL
// Массив = Новый Массив;
// Массив.Добавить(Тип("NULL"));
// Используем явное описание типов из колонок таблицы
Массив = Таб.Колонки[2].ТипЗначения.Типы();
Массив.Добавить(Тип("NULL"));
ОписаниеТиповС = Новый ОписаниеТипов(Массив);
Также важно проверить наличие «зацикливания» в спецификациях и комплектации. Если отладчик зависает на итерации по массиву комплектов, попробуйте проанализировать структуру МассивКомплектов. Если в нем бесконечно прибавляются элементы, значит, в справочнике Номенклатура или Спецификации допущена логическая ошибка: товар является составной частью самого себя.
Если вы используете старые версии платформы (например, 8.2.15), крайне рекомендуем выполнить переход на актуальные релизы 8.3. В новых версиях существенно переработан механизм трансляции запросов к СУБД. Кроме того, рассмотрим настройки самого SQL-сервера:
CXPACKET и зависаниям.tempdb вынесена на быстрый диск (SSD). Корректировка активно использует временные таблицы, и медленный tempdb может стать «бутылочным горлышком».Подведем итог: если закрытие месяца виснет на корректировке стоимости, не спешите сразу переписывать код. Сначала выполните тестирование и исправление в конфигураторе и очистку кэша SQL. Если это помогает лишь временно — переходите к оптимизации запросов, избавляясь от конструкции В ИЕРАРХИИ внутри виртуальных таблиц. Совокупность технических настроек сервера (MAXDOP) и грамотного написания запросов позволяет сократить время закрытия месяца с нескольких часов до нескольких минут.