Администрирование · 10 мин
Как ускорить запись в регистр сведений в 1С
Почему медленно пишется регистр сведений в 1С и как ускорить запись: пакетная запись, индексы, блокировки, отказ от лишних операций. Практические рекомендации.
Медленная запись в регистр сведений — одна из самых частых причин «тормозов» обменов, загрузок и регламентных операций в 1С. Типичная ситуация: обработка, которая в тестовой базе отрабатывала за минуты, в рабочей базе выполняется часами, а пользователи жалуются на конфликты блокировок.
Причины почти всегда лежат в нескольких областях: запись выполняется по одной записи вместо пакетной, регистр перегружен индексами или измерениями, каждая запись идёт в отдельной транзакции, а параллельные процессы конкурируют за одни и те же строки таблицы. Большинство этих проблем устраняется без покупки нового оборудования.
Ниже разобраны конкретные приёмы: как переписать код на пакетную запись, какие настройки регистра влияют на скорость, как снизить конкуренцию за блокировки и как проверить, что оптимизация действительно сработала.
Как понять, что проблема именно в записи регистра
Прежде чем менять код, убедитесь, что узкое место — именно регистр сведений, а не запросы к другим таблицам или сеть. Самый простой способ — замер производительности через конфигуратор (Отладка → Замер производительности) на участке обработки.
Характерные признаки проблемы с записью: в замере доминируют строки Записать() и обращения к конкретной таблице регистра; время растёт линейно или хуже по мере роста объёма данных; в технологическом журнале видны события TLOCK и TDEADLOCK по таблице регистра.
Ищите в коде цикл с МенеджерЗаписи.Записать() внутри
Проверьте технологический журнал на события TDEADLOCK
Посмотрите состав индексов и число записей в регистре
Пишите наборами записей, а не по одной записи
Самая распространённая ошибка — запись через РегистрыСведений.ИмяРегистра.СоздатьМенеджерЗаписи() в цикле. Каждый вызов Записать() у менеджера записи — это отдельное обращение к СУБД: проверка существования записи, вставка или обновление, обновление индексов. На десятках тысяч записей накладные расходы становятся огромными.
Правильный подход — сформировать набор записей, заполнить его в памяти и записать одним вызовом НаборЗаписей.Записать(Истина). Если регистр независимый и нужно добавить записи без затирания существующих, набирайте порции по несколько тысяч строк и записывайте пакетами, предварительно установив отбор по измерениям порции или используя запись без замещения через Записать(Ложь) там, где это допустимо по логике.
Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(ТекущаяДата);
Для Каждого Строка Из ТаблицаДанных Цикл
Запись = Набор.Добавить();
Запись.Период = ТекущаяДата;
Запись.Номенклатура = Строка.Номенклатура;
Запись.Цена = Строка.Цена;
КонецЦикла;
Набор.Записать(Истина);При очень больших объёмах (сотни тысяч записей) не пытайтесь записать всё одним набором: разбивайте данные на порции по 5–50 тысяч строк. Слишком большая транзакция раздувает журнал СУБД и удерживает блокировки дольше, что вредит параллельной работе пользователей.
Сократите число транзакций и лишних операций
Каждая запись в отдельной транзакции — это фиксация в журнале СУБД, снятие и установка блокировок. Объединение записей в одну транзакцию внутри порции сокращает эти накладные расходы в разы. Если запись идёт внутри явной транзакции загрузки документов, проверьте, не пишется ли регистр многократно при записи каждого документа — часто выгоднее накопить данные и записать один раз в конце.
Отдельно проверьте подписки на события и обработчики ПриЗаписи: нередко в них скрыты запросы к справочникам, пересчёты и даже запись других регистров. Тяжёлый обработчик, срабатывающий на каждую запись, способен замедлить процесс в десятки раз. Для массовых загрузок используйте ОбменДанными.Загрузка = Истина у набора записей — это отключает бизнес-логику обработчиков, но требует, чтобы вы сами гарантировали корректность данных.
Оптимизируйте структуру регистра и индексы
Каждый индекс ускоряет чтение, но замедляет запись: при вставке строки СУБД обновляет все индексы таблицы. Проверьте в конфигураторе свойства реквизитов регистра — флаг «Индексировать» часто проставлен «на всякий случай» у полей, по которым никто не ищет. Уберите индексацию у реквизитов, не участвующих в отборах и соединениях.
Также критичен состав измерений. Чем больше измерений, тем шире ключ и тем тяжелее кластерный индекс. Если часть измерений фактически используется как данные (по ним не строят отборы), переведите их в реквизиты или ресурсы — это уменьшит ключ и ускорит как запись, так и реструктуризацию.
Для подчинённых регистратору регистров сведений помните: их записи физически хранятся с ключом по регистратору. Массовое перепроведение документов каждый раз перезаписывает движения — здесь выигрыш даёт отключение итогов связанных регистров накопления на время загрузки и пакетное проведение через ОбработкаПроведения.
Снизьте конкуренцию за блокировки
В клиент-серверном режиме 1С использует управляемые блокировки. Если два процесса пишут в один регистр с пересекающимися отборами, один ждёт другого, а при невезении возникает взаимоблокировка и откат транзакции. Симптом — ошибки «Конфликт блокировок при выполнении транзакции» в журнале регистрации.
Практические меры: запускайте массовые загрузки в период минимальной активности пользователей; разделяйте параллельные потоки по непересекающимся диапазонам измерений (например, по организациям или складам); сокращайте длительность транзакций — не выполняйте внутри одной транзакции запись регистра и тяжёлые расчёты.
Если регистр используется как оперативная очередь или таблица статусов и запись в него идёт из многих сеансов одновременно, рассмотрите изменение архитектуры: замену на регистр с записью только добавлением, очередь через план обмена или фоновые задания с последовательной обработкой.
Как выбрать действие
Используйте серверные возможности СУБД
Если код оптимизирован, а скорость всё равно не устраивает, смотрите на уровень СУБД. Убедитесь, что для базы выполняется регламентное обслуживание: обновление статистики и перестроение (дефрагментация) индексов. Устаревшая статистика приводит к неоптимальным планам запросов, включая операции вставки с проверкой существования.
Для действительно массовых одноразовых загрузок (миграции, первичное заполнение) допустим прямой импорт средствами СУБД с последующей проверкой данных, но это задача для опытного администратора: структура таблиц 1С недокументирована, и ошибка приведёт к повреждению данных. Всегда делайте резервную копию перед такими операциями.
На файловых базах возможности ограничены: там основной выигрыш даёт пакетная запись, отказ от индексов и работа в монопольном режиме. Если объёмы растут, переход на клиент-серверный вариант сам по себе ускоряет массовые записи за счёт нормального механизма журналирования СУБД.
Проверьте результат оптимизации
После изменений повторите замер производительности на том же объёме данных и сравните время. Хороший признак — сокращение числа обращений к СУБД пропорционально уменьшению числа вызовов Записать().
Контрольные точки: длительность загрузки эталонного пакета данных, отсутствие ошибок блокировок в журнале регистрации во время теста, корректность итогового содержимого регистра (сверьте количество и ключевые значения записей с источником).
Как проверить результат
Один вызов на порцию данных
Вызов на каждую строку источника
Нет ошибок конфликта блокировок
Повторяющиеся ошибки TLOCK/TDEADLOCK
Количество и значения совпадают с источником
Пропущенные или задвоенные записи
Сократилось в разы после оптимизации
Изменилось незначительно или выросло
Что важно запомнить
Основной резерв скорости — пакетная запись наборами вместо поштучной, минимум индексов и измерений, короткие транзакции и разнесение конкурирующих процессов. Сначала замерьте, потом меняйте — и проверяйте результат на эталонном объёме данных.
Частые вопросы
Что быстрее: Записать(Истина) или Записать(Ложь) у набора записей?
Записать(Истина) замещает существующие записи по установленным отборам — СУБД выполняет удаление и вставку. Записать(Ложь) только добавляет и при конфликте ключей выдаст ошибку. По скорости разница обычно невелика; выбирайте режим по бизнес-логике, а не по производительности.
Помогает ли отключение итогов для регистра сведений?
У регистров сведений нет итогов в том смысле, как у регистров накопления. Отключение итогов актуально для связанных регистров накопления при массовом проведении документов. Для периодических регистров сведений есть отдельные таблицы среза последних/первых — если они не используются, отключите их в свойствах регистра: это реально ускоряет запись.
Безопасно ли писать в регистр напрямую через SQL?
Нет, это рискованный приём. Структура таблиц 1С не документирована, при обновлении конфигурации она может измениться, а ошибка в данных приведёт к рассогласованию, которое сложно диагностировать. Прямой SQL допустим только для разовых миграций опытным специалистом и только после резервного копирования.
Какой размер порции записи выбрать?
Универсального числа нет: ориентируйтесь на диапазон от нескольких тысяч до десятков тысяч записей. Подберите опытным путём: если транзакция длится дольше десятков секунд или растут блокировки — уменьшайте порцию; если накладные расходы на фиксацию транзакций заметны в замере — увеличивайте.
Почему запись в тестовой базе быстрая, а в рабочей — медленная?
Чаще всего дело в объёме данных и параллельной нагрузке: в рабочей базе таблица больше, индексы фрагментированы, а пользователи конкурируют за блокировки. Повторите замер в рабочей базе в нерабочее время — если скорость восстановилась, проблема в конкуренции, а не в коде.