Гайд 1С: Оптимизация записи наборов записей регистров с отбором по регистратору
- Ошибки
Конфликт блокировок при выполнении транзакциипри одновременном проведении разнородных документов. - Эскалация блокировок СУБД с уровня отдельных строк до полной блокировки таблицы регистра.
- Длительное время выполнения метода
НаборЗаписей.Записать().
1. Обязательный отбор по Регистратору
При записи наборов записей подчиненных регистров накопления, бухгалтерии и сведений отбор по регистратору должен устанавливаться всегда строго перед операцией чтения или очистки:
// ПРАВИЛЬНЫЙ ШАБЛОН ЗАПИСИ НАБОРА
Набор = РегистрыНакопления.Взаиморасчеты.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
// Заполнение данных набора
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
Движение = Набор.Добавить();
Движение.Период = Дата;
Движение.Регистратор = СсылкаНаДокумент;
Движение.Контрагент = СтрокаТЧ.Контрагент;
Движение.Сумма = СтрокаТЧ.Сумма;
КонецЦикла;
// Запись без очистки чужих блокировок
Набор.Записать(Истина); // Замещать = Истина2. Очистка движений документа без чтения в память
Если требуется удалить старые движения документа перед перепроведением, используйте пустой набор с флагом замещения вместо ручного удаления строк:
Набор = РегистрыНакопления.ТоварыНаСкладах.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
Набор.Записать(Истина); // Мгновенное удаление на уровне СУБД (DELETE WHERE Recorder = @P1)3. Разделение итогов регистров накопления
В свойствах метаданных регистра накопления включите свойство Разрешить разделение итогов. Это исключает взаимоблокировки документов при одновременной записи движений по одним и тем же измерениям.
Частые вопросы (FAQ)
Почему возникает взаимоблокировка при записи без флага Замещать = Истина?
При Замещать = Ложь платформа пытается выполнить объединение существующих записей в СУБД с новыми, что требует наложения предикатных S-блокировок и последующего их повышения до X-блокировок, вызывая классический Deadlock.
Как механизм разделения итогов устраняет взаимоблокировки?
Платформа добавляет скрытое поле 'НомерЗаписи/Разделитель' в таблицу итогов, позволяя разным сессиям параллельно увеличивать или уменьшать итог по одинаковым измерениям в разных физических строках таблицы.
Нужно ли считывать существующий набор (Набор.Прочитать()), если нужно просто добавить одну запись?
Если набор большой, вычитывать его в память rphost неоптимально. Лучше использовать независимые регистры сведений с точечным отбором или формировать движения через перепроведение документа.
Что генерирует СУБД при записи набора с флагом Замещать = Истина?
СУБД выполняет быструю атомарную операцию DELETE по кластерному индексу регистратора и последующую пакетную вставку новых строк через BULK INSERT.