Закрытие месяца 1С длится часами: где теряется время и как ускорить
Иван Недомолков · Dərc edilib: · Yenilənib:
Закрытие месяца, которое раньше проходило за вечер, начинает занимать всю ночь, а к кварталу - полторы. Бухгалтерия ставит расчёт на ночь и надеется, что к утру он не упадёт; если упал - день потерян. При этом “оно просто медленное” - не диагноз, а капитуляция. Время закрытия месяца складывается из конкретных этапов, каждый из которых замеряется, и почти всегда есть два-три, которые съедают львиную долю, а остальные не трогать вообще.
Ниже - где именно теряется время при закрытии месяца и регламентных операциях 1С, как это увидеть инструментально, а не на глаз, и что реально ускоряют на практике. Тон - без обещаний “ускорим в 10 раз”: сначала измеряют, потом чинят.
Если закрытие проходит быстро, но после него у части продаж себестоимость ноль, это другая беда, и скорость тут ни при чём: почему себестоимость ноль после закрытия месяца и какой документ виноват.
Где теряется время
Закрытие месяца - это не одна операция, а цепочка, и медленной её делают, как правило, не все звенья сразу.
Перепроведение документов. Самый частый пожиратель времени. Если в течение месяца документы перепроводились задним числом, восстановление последовательности и повторное проведение больших пачек может занимать часы. Каждый документ пересчитывает движения по регистрам, а если внутри проведения есть запрос остатков в цикле по строкам - время растёт нелинейно.
Восстановление последовательности. Проведённые задним числом документы рвут последовательность, и регламентная операция прогоняет её заново от точки разрыва до конца периода. Один документ, проведённый первым числом задним числом, может заставить пересчитать весь месяц.
Тяжёлые регламентные расчёты. Расчёт себестоимости, закрытие затратных счетов, распределение косвенных расходов, начисление амортизации, переоценка валютных остатков - это сложные алгоритмы, работающие с большими объёмами движений. На больших базах именно они, а не проведение, часто оказываются главным этапом.
Блокировки и конкуренция. Если закрытие идёт не в одиночестве, а параллельно с чьей-то работой или с другим фоновым заданием, операции встают в очередь на блокировках. “Медленно” превращается в “висит”, и разница принципиальна: медленный расчёт грузит процессор, а заблокированный - просто ждёт, не делая ничего.
Устаревшая статистика и итоги. После массовых загрузок и проведений статистика СУБД устаревает, планы запросов “слетают”, и запрос, укладывавшийся в секунды, начинает сканировать миллионы строк. Отдельная история - таблицы итогов регистров: если период рассчитанных итогов выбран неудачно, каждый расчёт остатков лезет считать движения вместо готового итога.
Медленно ≠ блокировки: сначала разделить
Это разделение - первый и самый важный шаг диагностики, потому что лечится каждый случай по-своему. Операция может тормозить по двум принципиально разным причинам:
- Она реально работает и грузит сервер - процессор занят, диск читает миллионы строк. Лечится оптимизацией кода и запросов.
- Она ничего не делает и ждёт - стоит на блокировке, пока её держит другой процесс. Лечится разбором блокировок, а не ускорением запроса - ускорять тут нечего, оно и так простаивает.
Диагностировать “на глаз” их невозможно: и то, и другое выглядит как “закрытие висит два часа”. Разделяет их только инструмент. Показательный пример из нашей практики: в проекте с “вечерними зависаниями касс” все были уверены, что виноваты блокировки, - а замер показал ноль ожиданий на блокировках. Тормозил агрессивный параллелизм SQL на 48-ядерном сервере с заводскими настройками (cost threshold for parallelism = 5, MAXDOP = 0): сервер дробил на 48 потоков даже мелкие запросы, и они душили друг друга за ядра. Две настройки - и пик перестал быть лотереей. Если бы “лечили блокировки”, не нашли бы ничего.
Как диагностировать: техжурнал и замер по этапам
Оптимизация закрытия месяца начинается не с правки кода, а с измерения - иначе вы будете ускорять то, что и так быстро.
Замер по этапам. Первым делом - разложить закрытие на шаги и замерить каждый: перепроведение - столько, восстановление последовательности - столько, расчёт себестоимости - столько. Почти всегда картина оказывается неравномерной: два-три этапа съедают 80 % времени, остальные незаметны. Ускорять надо только эти два-три - оптимизировать быстрый этап бессмысленно, даже если он “выглядит неоптимальным”.
Технологический журнал 1С. Настраивается сбор событий по длительным запросам и ожиданиям на блокировках. Это даёт точную картину: какие именно запросы и чей код съедают время, где сервер ждёт на блокировке, а где считает. Не “закрытие медленное”, а “вот этот запрос в модуле расчёта себестоимости выполняется 40 минут и делает 200 млн логических чтений”.
Планы запросов SQL. Для запросов-виновников смотрим, как СУБД их выполняет на самом деле: сканирование таблицы вместо поиска по индексу, лишние соединения, четыре прохода по регистру там, где хватило бы одного. План показывает причину, а не симптом.
Статистика ожиданий СУБД. Отвечает на вопрос, во что упирается сервер целиком: диски, процессор, память или блокировки. Без неё легко “ускорять запросы”, когда сервер на самом деле упёрся в диск.
Что оптимизируют на практике
Когда виновники найдены и замерены, набор рычагов оказывается довольно предсказуемым.
| Что делаем | Против какой причины | Типичный эффект |
|---|---|---|
| Индексы под тяжёлые запросы расчётов | Сканирование вместо поиска | Кратный на конкретной операции |
| Переписывание запроса в цикле на set-based | Построчная обработка при проведении | В разы на проведении документа |
| Пересчёт и настройка периода итогов | Расчёт остатков “на лету” | Проценты-десятки % |
| Обновление статистики после загрузок | Слетевшие планы запросов | Восстановление до нормы |
| Настройка параллелизма SQL | Дробление мелких запросов / простой ядер | Кратный на пике |
| Разбор и устранение блокировок | Ожидание вместо работы | Убирает “зависания” |
| Порядок и параллельность этапов закрытия | Последовательное выполнение независимого | Сокращение общего окна |
Два примера из боевых проектов, чтобы это не звучало абстрактно:
- Документ, который “не проводился” 2 минуты → 17 секунд. Внутри проведения запрос остатков выполнялся в цикле по каждой строке документа. Переписан на один set-based запрос - и двухминутная операция стала укладываться в 17 секунд.
- Шесть тяжёлых управленческих отчётов: −22…−42 % времени при полностью идентичных данных. Результат “до” и “после” сверялся контрольной суммой SHA-256 - это принципиально: ускорение отчёта, который начал показывать другие цифры, не ускорение, а поломка.
Отдельный рычаг для по-настоящему тяжёлых пересчётов - параллелизм. В проекте розничной сети с 48-ядерным сервером правильная настройка параллелизма SQL убрала вечерние тормоза, которые все списывали на блокировки. А там, где платформенный пересчёт итогов не влезал в ночное окно (112 минут), перенос его на прямой SQL с побитовой сверкой против эталонного механизма сократил операцию до 21 минуты - при полной идентичности результата.
Честная оговорка про параллельность
Соблазн велик: “раз 48 ядер - давайте всё считать в 48 потоков”. На практике параллелизм помогает не везде и иногда вредит. Мелкие запросы, раздробленные на десятки потоков, тратят больше времени на координацию, чем на работу, и душат друг друга за ядра - ровно это мы и видели в кейсе с кассами. Параллельность окупается на действительно тяжёлых операциях с большими объёмами и не окупается на лёгких. Поэтому правильная настройка - это не “включить максимум”, а установить порог, ниже которого запрос выполняется одним потоком, и предел числа потоков на запрос. Конкретные значения зависят от железа и профиля нагрузки и подбираются по замеру.
Чего не надо оптимизировать
Важная часть честной оптимизации - знать, где остановиться. Если этап закрытия занимает две минуты из шести часов, переписывать его код бессмысленно, даже если он выглядит неаккуратным: выигрыш будет в пределах погрешности, а риск внести регресс - реальный. В одном из проектов часть отчётов после разбора мы оставили без изменений - узкое место было не в запросе, и переписывание не дало бы выигрыша. Не потратить бюджет заказчика на то, что не ускорится, - это тоже результат оптимизации, просто менее эффектный.
Чек-лист: с чего начать ускорение закрытия месяца
- Разложите закрытие на этапы и замерьте каждый. Найдите два-три, которые съедают большую часть времени. Остальное не трогайте.
- Разделите “медленно” и “висит”. Техжурнал покажет, где сервер работает, а где ждёт на блокировке. Это разные болезни.
- Проверьте статистику и итоги. После массовых загрузок обновите статистику; проверьте период рассчитанных итогов регистров. Если остатки в отчётах после закрытия не бьются с движениями, месяц и позицию поломки покажет Чек-ап итогов и остатков 1С, и пересчитывать придётся один-два месяца, а не всю базу.
- Разберите топовый запрос по плану. Сканирование, цикл, лишние проходы - самые частые находки, и самые благодарные для правки.
- Проверьте настройки параллелизма SQL. Заводские
MAXDOP= 0 иcost threshold= 5 на многоядерном сервере - частая скрытая причина тормозов. - Сверяйте результат до/после. Ускоренный расчёт обязан давать те же цифры - иначе это не оптимизация.
Коротко
Закрытие месяца длится часами не “вообще”, а на конкретных этапах - чаще всего это перепроведение с восстановлением последовательности, тяжёлые регламентные расчёты и запросы в цикле, а иногда - блокировки или неудачные настройки параллелизма SQL. Диагностируется это замером по этапам и технологическим журналом, а не догадками. Лечится точечно: индексы, переписывание горячих запросов на set-based, пересчёт итогов, обновление статистики, настройка параллелизма. Главное правило - сначала измерить, потом чинить, и сверять результат до/после, чтобы ускоренный расчёт давал те же цифры.
Готовые обработки по теме:
- Чек-ап СУБД под 1С - параллелизм, статистика, tempdb и журнал транзакций с вердиктом по каждому пункту: настройки сервера чаще всего и объясняют, почему расчёт идёт часами именно у вас.
- Авто-УНИЧТОЖИТЬ: оптимизатор временных таблиц - расставляет уничтожение временных таблиц в пакетных запросах. У тяжёлых расчётов закрытия таких пакетов много, и мусор в tempdb копится весь прогон.
- Трансформатор SQL → запрос 1С - когда медленный запрос найден со стороны СУБД и надо понять, какому месту конфигурации он соответствует.
Если закрытие месяца встало и хочется найти настоящую причину, а не наращивать железо, - мы делаем оптимизацию производительности 1С: диагностика по техжурналу и планам запросов, правки с замерами “до/после”, сверка данных контрольными суммами. Самый крупный наш проект с полным разбором - в кейсе “Обрезка базы 4,2 ТБ → 105 ГБ”. А если пока нужно просто понять, что тормозит, - начните с бесплатного экспресс-аудита: по его итогам вы получите список медленных операций с замерами и прогноз, что и насколько ускоряется.