В процессе эксплуатации высоконагруженных систем на базе 1С:Предприятие 8.3 и MS SQL Server системные администраторы и разработчики часто сталкиваются с аномальным поведением: запись набора записей в регистр накопления (например, ЗатратыНаВыпускПродукции) занимает значительное время (30-40 секунд), даже если записываемый набор абсолютно пуст. Проанализируем причины этой проблемы и рассмотрим пошаговые методы её решения.
Одной из наиболее частых причин «зависания» записи является настройка Max Degree of Parallelism (MAXDOP) в SQL Server. Когда этот параметр установлен в значение, отличное от 1 (например, 4 или 8), SQL Server пытается распараллелить выполнение запроса. В случае с 1С это часто приводит к обратному эффекту: накладные расходы на координацию потоков превышают выгоду от параллельного выполнения.
Рассмотрим ситуацию: изменение MAXDOP временно решает проблему, но через несколько часов тормоза возвращаются. Это происходит потому, что при смене настроек параллелизма SQL Server принудительно очищает Plan Cache (кэш планов запросов). Как только система генерирует новый «плохой» план запроса для записи в таблицу регистра, проблема повторяется.
Разберем, как принудительно очистить кэш планов для диагностики, не меняя глобальные настройки сервера:
-- Очистка кэша планов для всей базы данных
DBCC FREEPROCCACHE;
GO
Если после выполнения этой команды запись временно начала работать быстро, значит, корень проблемы именно в неоптимальном плане запроса, который выбирает оптимизатор SQL.
Начиная с SQL Server 2014, Microsoft внедрила новый механизм оценки количества строк (Cardinality Estimator). Для специфических структур таблиц 1С этот механизм иногда ошибается, полагая, что в таблице нужно просканировать миллионы строк там, где их нет. В результате вместо эффективного поиска по индексу (Index Seek) SQL Server выполняет полное сканирование таблицы (Index Scan).
Проанализируем ситуацию и попробуем переключить базу данных в режим использования старого оптимизатора, который зачастую работает с 1С более стабильно:
Это заставит SQL использовать логику версии 2012 года, которая более предсказуема для метаданных 1С.
Если статистика по индексам таблицы _AccumRg (движения) или _AccumRgT (итоги) устарела, SQL Server не может адекватно оценить стоимость операции удаления старого набора записей перед записью нового. Даже если мы записываем пустой набор, 1С всё равно инициирует транзакцию, в которой SQL пытается найти существующие записи по измерениям регистра.
Выясним, помогает ли ручное обновление статистики. Рассмотрим пример скрипта для конкретной таблицы (имя таблицы можно узнать через ПолучитьСтруктуруХраненияБазыДанных):
-- Обновление статистики для таблицы регистра с полным сканированием
UPDATE STATISTICS dbo._AccumRg22380 WITH FULLSCAN;
GO
Также важно проверить параметр Auto Update Statistics Asynchronously. Рекомендуется установить его в True, чтобы процесс обновления статистики не блокировал выполнение текущего запроса пользователя.
Иногда в регистрах накопления (особенно в оборотных) могут появляться записи с некорректными датами (например, год 2000 вместо 4000 или даты из далекого прошлого/будущего). При записи набора 1С выполняет пересчет итогов. Если диапазон дат в итогах «расползается» на тысячи лет, SQL Server может тратить колоссальное время на блокировку и сканирование этих диапазонов.
Посмотрим на пример запроса для проверки дат в таблице итогов:
-- Проверка минимальной и максимальной даты в таблице итогов
SELECT MIN(_Period), MAX(_Period) FROM dbo._AccumRgT22385;
Если вы обнаружите там даты типа 01.01.0001 или 31.12.3999 вне ожидаемых периодов, это явный признак того, что итоги регистра нужно пересчитать или очистить от мусорных записей.
Помимо самого MAXDOP, критически важен параметр Cost Threshold for Parallelism. По умолчанию он равен 5, что заставляет SQL Server пытаться распараллеливать даже очень простые («дешевые») запросы. Для систем на базе 1С рекомендуется поднять это значение до 50. Это гарантирует, что простые операции записи в регистры будут выполняться в одном потоке, не тратя время на инициализацию параллелизма.
Подводя итог, если вы столкнулись с задержкой записи в пустой набор, выполните следующие шаги:
DBCC FREEPROCCACHE для подтверждения проблемы с планами.Cost Threshold for Parallelism = 50).FULLSCAN.Такой комплексный подход позволяет устранить «плавающие» тормоза и стабилизировать время проведения документов, работающих с тяжелыми регистрами накопления.