При разработке высоконагруженных систем на платформе 1С:Предприятие 8.3 часто возникает дилемма: какой инструмент использовать для модификации данных в независимых регистрах сведений. Выбор между МенеджерЗаписи и НаборЗаписей — это не просто вопрос удобства кода, а стратегическое решение, влияющее на стабильность работы пользователей, скорость транзакций и вероятность возникновения дедлоков (deadlocks) в СУБД. Рассмотрим этот вопрос подробно, проанализировав механику работы каждого объекта.
Объект РегистрСведенийМенеджерЗаписи предназначен, прежде всего, для интерактивной работы. Его главная особенность заключается в том, что он оперирует одной конкретной записью, определяемой полным набором значений измерений (ключом записи). Разберем, что происходит «под капотом» при вызове метода Записать():
SELECT к СУБД, чтобы проверить, существует ли уже запись с таким ключом.UPDATE (если запись была), либо INSERT (если записи не было).Проанализируем ситуацию: если нам нужно записать 1000 уникальных записей, использование МенеджерЗаписи в цикле породит 1000 микро-транзакций (если они не обернуты в одну общую транзакцию НачатьТранзакцию()). Это создает существенную нагрузку на лог транзакций СУБД, но имеет важное преимущество — минимальную область блокировки. Каждая итерация блокирует только ту запись, с которой работает, не мешая другим пользователям читать остальные данные регистра.
Рассмотрим пример использования МенеджерЗаписи для записи уникальных данных:
Для Каждого СтрокаДанных Из МассивНовыхЗаписей Цикл
Менеджер = РегистрыСведений.МойРегистр.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(Менеджер, СтрокаДанных);
// Менеджер запишет данные, предварительно проверив их существование
Менеджер.Записать(Истина);
КонецЦикла;
Объект РегистрСведенийНаборЗаписей является основным инструментом для программной модификации данных. В отличие от менеджера, набор работает с целой выборкой, ограниченной фильтром (отбором). По умолчанию запись набора происходит по принципу «полного замещения» в рамках установленного отбора.
Выясним причину высокой скорости набора записей. При вызове Набор.Записать(Истина) платформа выполняет:
DELETE удаляет все существующие записи в регистре, попадающие под установленный Отбор.INSERT вставляет все записи, содержащиеся в коллекции набора.Это значительно быстрее, чем 1000 отдельных UPDATE, так как СУБД выполняет операции пакетами. Однако здесь кроется главная опасность — блокировки. Если отбор не установлен или установлен по неиндексированным полям, 1С может заблокировать значительный диапазон данных или даже всю таблицу (эскалация блокировок в MS SQL Server), что сделает невозможным чтение данных другими пользователями на время транзакции.
Если стоит задача просто добавить новые записи, о которых заранее известно, что их еще нет в регистре (например, логи или уникальные события), мы можем использовать самый быстрый метод — запись набора без замещения. Проанализируем пример кода:
Набор = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
// Добавляем новые записи в коллекцию набора
Для Каждого Строка Из ТаблицаНовыхДанных Цикл
НоваяЗапись = Набор.Добавить();
ЗаполнитьЗначенияСвойств(НоваяЗапись, Строка);
КонецЦикла;
// Ключевой момент: ложь в параметре Замещать
// Платформа пропустит стадию DELETE и выполнит только INSERT
Набор.Записать(Ложь);
В этом режиме НаборЗаписей работает максимально эффективно, не тратя время на поиск и удаление старых данных. Но помните: если в наборе окажется запись, ключ которой уже есть в базе, СУБД вернет ошибку уникальности.
Скорость записи в регистр напрямую зависит от его структуры. В независимых регистрах сведений 1С строит кластерный индекс по всем измерениям в том порядке, в котором они расположены в конфигураторе. Разберем, как это влияет на производительность:
Селективность измерений: Рекомендуется располагать измерения от самого часто используемого к менее частому. Однако для записи важнее физическая фрагментация. Если вы записываете данные вразнобой относительно кластерного индекса, SQL-сервер будет вынужден постоянно перестраивать страницы данных (Page Splits), что резко замедляет процесс.
Если ваш регистр активно читается, убедитесь, что порядок измерений совпадает с порядком полей в наиболее тяжелых запросах. Например, если отчеты всегда строятся по Организации и Контрагенту, именно они должны быть первыми измерениями. Это обеспечит «попадание» в индекс и ускорит выборку.
Рассмотрим ситуацию: регистр сведений содержит 1.5 миллиона строк и активно используется для RLS (ограничения прав) или онлайн-проверок. Если вы начнете записывать в него 1000 строк через НаборЗаписей с широким отбором, чтение для других пользователей может «встать» в очередь из-за X-блокировок (Exclusive) на уровне страниц или таблиц СУБД.
В таких случаях МенеджерЗаписи, запущенный в фоновом задании, может оказаться предпочтительнее. Несмотря на то, что общая длительность записи будет выше (например, 60 секунд против 2 секунд у набора), каждая отдельная блокировка будет мгновенной и точечной. Пользователи даже не заметят процесса обновления данных.
Важный совет: Если вы используете управляемые блокировки, обязательно устанавливайте объект БлокировкаДанных перед началом массовой записи. Это позволит платформе более интеллектуально управлять очередью доступа к ресурсам СУБД.
Подведем итог нашему анализу и определим правила выбора:
Отбор по всем измерениям, входящим в индекс.Выяснив все нюансы, мы можем сделать вывод: универсального инструмента не существует. НаборЗаписей — это скорость и пакетность, а МенеджерЗаписи — это атомарность и интерактивность. Правильное сочетание этих инструментов обеспечит вашей системе на 1С высокую производительность и комфортную работу пользователей.