Почему при заполнении документа «Начисление зарплаты» в 1С:ЗУП 3.1 происходит запись в базу данных?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

Каждый технический специалист, впервые столкнувшийся с архитектурой решений 1С на платформе «1С:Предприятие 8.3» (в частности, 1С:ЗУП 3.1, 1С:ERP или 1С:Комплексная автоматизация), испытывает легкое недоумение при анализе транзакций. Кажется нелогичным, что простое нажатие кнопки «Заполнить» в документе НачислениеЗарплатыИВзносов инициирует непосредственную запись данных в таблицы СУБД, минуя стандартный этап проведения документа. В этой статье мы подробно разберем, почему разработчики фирмы 1С приняли такое архитектурное решение, какую роль играет регистр сведений ГрафикиРаботыПоВидамВремени, с какими проблемами можно столкнуться и как их правильно решать.

В чем суть проблемы и почему это «так задумано»?

Рассмотрим стандартное поведение системы. Обычно документы в 1С работают по классическому принципу: пользователь открывает форму, нажимает кнопку заполнения, система рассчитывает данные в оперативной памяти и выводит их на экран. Запись в базу данных происходит только при явном нажатии кнопки «Записать» или «Провести». Однако в подсистеме расчета зарплаты ЗУП 3.1 логика иная.

При нажатии кнопки «Заполнить» система обращается к серверу и выполняет транзакционную запись в независимый регистр сведений ГрафикиРаботыПоВидамВремени. Это необходимо для обеспечения производительности расчетных механизмов. Выясним причину такого поведения подробнее.

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

  1. Общий график работы сотрудника (например, пятидневка или сменный график).
  2. Индивидуальные графики, введенные на конкретный месяц.
  3. Документы отклонений (больничные, отпуска, командировки).
  4. Документы фактического учета времени (табели, переработки, работа в выходные дни).

Если бы система выполняла все эти соединения динамически в оперативной памяти («на лету») в момент расчета каждого сотрудника, то расчет базы для крупного предприятия с тысячами работников занимал бы долгие часы. Для оптимизации этого процесса разработчики 1С создали плоскую служебную таблицу — регистр сведений ГрафикиРаботыПоВидамВремени.

Записи в этом регистре формируются так называемым методом «по запросу». Когда расчетный механизм подготавливает данные для заполнения документа, он проверяет наличие актуального плоского графика в СУБД для каждого рассчитываемого сотрудника. Если готовых данных нет или они устарели, система мгновенно рассчитывает их и физически записывает в базу данных. Это позволяет последующим тяжелым запросам СУБД быстро соединять таблицы начислений с проиндексированными физическими таблицами времени.

Архитектурный секрет измерения «График работы»

Проанализируем структуру регистра ГрафикиРаботыПоВидамВремени. Одним из ключевых его измерений является ГрафикРаботы. На первый взгляд, это обычная ссылка на справочник графиков сотрудников. Однако данное измерение имеет составной тип данных. В зависимости от условий расчета туда могут записываться разные типы объектов:

Типичные проблемы и ошибки этой архитектуры

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

1. Ошибка «Запись с такими ключевыми полями существует!»

Это классическая коллизия блокировок или кэширования. Она возникает, когда расчетный механизм пытается записать набор записей в регистр ГрафикиРаботыПоВидамВремени, но в базе данных уже существуют аналогичные ключи (например, из-за незавершенных сеансов, некорректно удаленных документов или при одновременной работе нескольких расчетчиков в одном периоде).

Для устранения этой ошибки разберем несколько шагов:

  1. Выполнить очистку серверного и клиентского кэша базы данных.
  2. Временно перенести дату регистрации в документе начисления на другой месяц, очистить табличную часть, вернуть месяц обратно и перезаполнить документ.
  3. Проверить наличие дублирующихся кадровых документов отклонений (например, когда на один и тот же день введены и больничный лист, и командировка).

2. Лавинообразное разрастание информационной базы

Поскольку персональные записи генерируются под каждого сотрудника при малейшем отклонении от графика, регистр очень быстро раздувается. В базах крупных холдингов количество записей в нем может превышать 10–15 миллионов строк. Это приводит к значительному увеличению размера файла базы данных (или таблиц на SQL-сервере), замедлению процессов резервного копирования и потенциальным ошибкам нехватки памяти (Out of Memory) при проведении тестирования и исправления.

3. Появление «призраков» в отчетах

Если пользователь нажал кнопку «Заполнить», система сгенерировала и записала плоские графики в регистр, но затем пользователь решил закрыть документ без сохранения. В этот момент временные записи графиков остаются в базе данных. В большинстве случаев это не мешает работе, так как при следующем расчете данные перезапишутся, однако в редких случаях это может приводить к временным расхождениям в аналитических отчетах по рабочему времени.

Можно ли очистить («грохнуть») этот регистр?

Как совершенно верно отметил один из участников обсуждения на форуме, данные в этом регистре носят подчиненный, технологический характер. Это означает, что полное программное удаление записей из регистра ГрафикиРаботыПоВидамВремени не приведет к потере ведения учета или поломке базы данных.

При первой же необходимости (например, при расчете аванса, заполнении нового документа начисления зарплаты или расчете среднего заработка для отпуска) система автоматически обнаружит отсутствие записей и сгенерирует их заново. Тем не менее, делать полную очистку в разгар рабочего дня в крупной компании настоятельно не рекомендуется.

Рассмотрим по шагам последствия тотальной очистки регистра в рабочей базе:

  1. Экстремальная нагрузка на сервер: при первой же попытке массового заполнения документов система начнет в один поток рассчитывать и записывать миллионы строк графиков заново. Это вызовет сильные блокировки таблиц СУБД и парализует работу пользователей.
  2. Риск изменения старых периодов: если вы решите пересчитать документы прошлых периодов, старые расчеты могут «поплыть», если исходные кадровые данные за те периоды были изменены задним числом.

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


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

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

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

← На главную