При разработке и оптимизации конфигураций на платформе 1С:Предприятие часто возникает вопрос: какой объект использовать для изменения данных в независимых регистрах сведений — МенеджерЗаписи или НаборЗаписей? На первый взгляд оба объекта позволяют записывать, изменять и удалять строки, однако внутренние механизмы платформы, взаимодействие с СУБД и поведение транзакций у них существенно различаются. Проанализируем ключевые особенности каждого подхода, разберем влияние на производительность и выясним, в каких ситуациях следует применять тот или иной объект.
Рассмотрев поведение платформы 1С при работе с регистрами сведений, можно отметить, что МенеджерЗаписи не является принципиально отдельным механизмом хранения. Когда в программном коде создается и записывается объект МенеджерЗаписи, платформа на внутреннем уровне формирует объект НаборЗаписей с отбором по всем измерениям и периоду (ключу записи) и выполняет его сохранение.
Однако существуют важные архитектурные нюансы:
МенеджерЗаписи нет собственного модуля объекта. Все обработчики событий (такие как ПередЗаписью и ПриЗаписи) исполняются в модуле набора записей соответствующего регистра.МенеджерЗаписи с изменением значений измерений платформа выполняет удаление старой записи по прежнему ключу и добавление новой. В результате этого обработчики событий модуля набора записей могут быть вызваны повторно.НаборЗаписей подписки на события срабатывают один раз на весь набор. Если же выполняются операции над несколькими объектами МенеджерЗаписи, подписки и события модуля вызываются отдельно для каждого менеджера.Посмотрим на то, как запись данных происходит на уровне системы управления базами данных (СУБД). Процесс записи набора строк состоит из следующих шагов:
Замещать = Истина), платформа сначала отправляет запрос DELETE для удаления существующих записей, подпадающих под установленный Отбор.INSERT для каждой записи.Записать(Ложь), этап удаления DELETE пропускается, и платформа сразу переходит к выполнению команд INSERT.Главная разница в производительности заключается в управлении транзакциями:
При использовании объекта НаборЗаписей операции удаления и вставки всей группы строк автоматически оборачиваются платформой в одну транзакцию СУБД. При попытке записать множество строк поочередно через МенеджерЗаписи без явного управления транзакциями платформа будет открывать и фиксировать транзакцию для каждой строки отдельно. Это создает колоссальную нагрузку на дисковую подсистему и сервер базы данных.
Если требуется записать несколько менеджеров записи, их обязательно следует обернуть в явную транзакцию:
НачатьТранзакцию();
Для Каждого СтрокаДанных Из МассивДанных Цикл
МенеджерЗаписи = РегистрыСведений.МойРегистр.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтрокаДанных);
МенеджерЗаписи.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Выясним, какие риски и преимущества несут в себе оба объекта с точки зрения защиты данных и параллельной работы пользователей.
Безопасность кода: Набор записей требует внимательного отношения к отборам. Если создать объект НаборЗаписей, не установить у него Отбор и вызвать метод Записать() (или Записать(Истина)), платформа полностью очистит содержимое всего регистра сведений. Объект МенеджерЗаписи лишен этого риска, так как он адресно работает с одной записью по ключевым полям.
Управляемые блокировки: МенеджерЗаписи накладывает точечную блокировку исключительно на конкретный ключ записи (все измерения и период). НаборЗаписей блокирует диапазон данных, определенный отбором. Если отбор установлен не по всем измерениям, блокируется группа данных, что может приводить к ожиданиям на блокировках при параллельной работе нескольких сеансов.
Разберем пример эффективной записи большого массива данных в регистр сведений с использованием объекта НаборЗаписей. Для достижения максимальной производительности рекомендуется разбивать данные на пакеты (например, по 1000–5000 строк) и записывать их без предварительного удаления (если гарантировано отсутствие дублей по ключу):
НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
Счетчик = 0;
Для Каждого СтрокаИсточник Из ТаблицаИсточника Цикл
НоваяЗапись = НаборЗаписей.Добавить();
ЗаполнитьЗначенияСвойств(НоваяЗапись, СтрокаИсточник);
Счетчик = Счетчик + 1;
// Записываем порциями по 1000 строк
Если Счетчик % 1000 = 0 Тогда
// Замещать = Ложь отключает выполнение команды DELETE перед вставкой
НаборЗаписей.Записать(Ложь);
НаборЗаписей.Очистить();
КонецЕсли;
КонецЦикла;
// Записываем остаток
Если НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Записать(Ложь);
НаборЗаписей.Очистить();
КонецЕсли;
Сводя воедино особенности обоих объектов, сформируем рекомендации по их применению:
МенеджерЗаписи: Для точечного чтения, изменения или удаления одной конкретной строки регистра сведений в интерактивных формах или редких точечных операциях. Это гарантирует защиту от случайного удаления других строк и накладывает минимальную точечную блокировку.НаборЗаписей: Для массовой обработки, загрузки данных, заполнения регистров пакетами, а также при необходимости полностью обновить данные по конкретному фильтру (например, по конкретному аналитическому разрезу).