Как быстро очистить большой регистр сведений на миллионы записей в 1С?

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

Часто в процессе поддержки или разработки высоконагруженных баз данных 1С мы сталкиваемся с необходимостью выполнить универсальную очистку данных или полностью очистить огромный регистр сведений. Например, регистр соответствия объектов для обмена может содержать десятки миллионов записей. Проанализируем ситуацию: попытка очистить такой объем данных "в лоб", создав набор записей и записав его с пустым значением, неизбежно заканчивается ошибкой "Недостаточно памяти" (аналогичная проблема возникает при массовом удалении помеченных объектов).

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

Почему возникают ошибки при стандартном подходе?

Ошибка "Недостаточно памяти" при записи пустого набора (или даже при попытке обычной реструктуризации) возникает из-за того, что платформа пытается обработать все миллионы записей разом, исчерпывая лимиты выделяемой оперативной памяти. Для 32-разрядных клиентов и рабочих процессов сервера 1С это ограничение составляет около 2 ГБ.

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

Способ 1. Очистка таблицы средствами СУБД (TRUNCATE TABLE)

Если база данных работает в клиент-серверном варианте (MS SQL Server, PostgreSQL и др.), самым быстрым и эффективным методом будет очистка таблицы напрямую средствами СУБД. Разница в скорости колоссальна — очистка происходит практически мгновенно.

Разберем по шагам, как это сделать:

  1. Сначала нам нужно узнать физическое имя таблицы нашего регистра в базе данных SQL. Для этого можно воспользоваться встроенной функцией ПолучитьСтруктуруХраненияБазыДанных() или специализированными обработками.
  2. Допустим, мы выяснили, что таблице "Соответствие объектов для обмена" соответствует физическая таблица _InfoRg7078.
  3. Откроем консоль управления сервером СУБД (например, SQL Server Management Studio), найдем нашу базу данных и выполним следующий запрос:

TRUNCATE TABLE [ИмяВашейБазы].[dbo].[_InfoRg7078]

Важное примечание: Применение TRUNCATE TABLE удаляет данные минуя журнал транзакций построчно, что делает операцию сверхбыстрой и не ведет к сильной фрагментации индексов. Однако помните, что 1С не "знает" о прямом вмешательстве в СУБД. Этот метод рекомендуется использовать с осторожностью и обязательно после создания резервной копии.

Если очистку должен запускать конечный пользователь из режима Предприятия, мы можем настроить в СУБД Windows Authentication (авторизацию системой), создать отдельного пользователя с правами только на соединение и операцию DELETE/TRUNCATE для конкретной таблицы, и выполнять SQL-запрос напрямую из кода 1С через ADO.

Способ 2. Порционное удаление через код 1С (для файловых и клиент-серверных баз)

Если прямое вмешательство в SQL невозможно, мы можем оптимизировать код 1С. Рассмотрим подробнее правильную структуру порционного удаления. Чтобы не переполнять память и не нагружать диск одиночными транзакциями, удалять данные нужно порциями (по 1000–5000 записей), оборачивая каждую порцию в транзакцию.

Посмотрим на пример оптимизированного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1000
    |   СоответствиеОбъектовДляОбмена.УзелОбмена,
    |   СоответствиеОбъектовДляОбмена.СобственнаяСсылка,
    |   СоответствиеОбъектовДляОбмена.СсылкаВДругойИБ
    |ИЗ
    |   РегистрСведений.СоответствиеОбъектовДляОбмена КАК СоответствиеОбъектовДляОбмена";

Пока Истина Цикл
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Количество() = 0 Тогда
        Прервать;
    КонецЕсли;
    
    НачатьТранзакцию();
    Попытка
        Пока Выборка.Следующий() Цикл
            МЗ = РегистрыСведений.СоответствиеОбъектовДляОбмена.СоздатьМенеджерЗаписи();
            МЗ.УзелОбмена = Выборка.УзелОбмена;
            МЗ.СобственнаяСсылка = Выборка.СобственнаяСсылка;
            МЗ.СсылкаВДругойИБ = Выборка.СсылкаВДругойИБ;
            МЗ.Прочитать();
            
            Если МЗ.Выбран() Тогда
                МЗ.ОбменДанными.Загрузка = Истина; // Отключаем регистрацию на узлах обмена
                МЗ.Удалить();
            КонецЕсли;
        КонецЦикла;
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        // Обработка ошибки (запись в ЖР и т.д.)
        Прервать;
    КонецПопытки;
КонецЦикла;

Ключевые моменты этого кода:

Способ 3. Безопасное пересоздание регистра в Конфигураторе

Если в регистре не осталось ничего нужного, можно решить проблему инструментами разработчика. Однако банальное удаление регистра в конфигураторе и нажатие F7 приведет к всё той же ошибке нехватки памяти из-за попытки платформы удалить огромную таблицу в рамках одной транзакции реструктуризации.

Чтобы реструктуризация прошла успешно, разобьем процесс на три безопасных этапа:

  1. В Конфигураторе переименовываем наш проблемный регистр (например, добавляем к имени "Удалить_").
  2. Создаем новый регистр (простым копированием структуры переименованного) и задаем ему оригинальное имя. Сохраняем конфигурацию базы данных (F7). На этом этапе у нас появляется новый пустой рабочий регистр.
  3. Теперь удаляем старый (переименованный) регистр из дерева конфигурации и снова нажимаем F7. Платформа просто удалит ("дропнет") старую физическую таблицу, что потребует значительно меньше ресурсов, чем построчная очистка.

Новые возможности платформы 8.3

В новых версиях платформы 1С (начиная с релизов 8.3.26 и 8.3.27) разработчики добавили новые, более умные алгоритмы записи наборов данных. К параметру РежимЗамещения были добавлены значения Удаление, Обновление и Слияние. Использование этих режимов позволяет платформе нативно формировать пакетные запросы для удаления данных, не перегружая кэш и оперативную память сервера.

Применяя комбинацию из этих методов, мы можем безопасно и быстро избавиться от миллионов лишних записей в базе данных, сохранив стабильность работы 1С-Предприятия.

← На главную