При работе с базами данных 1С:Предприятие 7.7 на платформе SQL часто возникает необходимость очистки справочников от большого объема данных. Стандартные методы встроенного языка, такие как перебор элементов и установка пометки удаления, работают крайне медленно из-за механизмов объектной обработки и контроля транзакций на каждый элемент. В этой статье мы подробно разберем, как ускорить этот процесс, используя прямые SQL-запросы, проанализируем риски использования команды TRUNCATE и рассмотрим наиболее безопасные "гибридные" методы.
Почему стандартный код работает долго? Когда мы используем конструкцию:
Спр = СоздатьОбъект("Справочник.Номенклатура");
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Спр.Удалить(1); // Или УстановитьПометкуУдаления(1)
КонецЦикла;
Платформа 1С выполняет множество действий для каждой записи: считывает объект, блокирует его, проверяет права, регистрирует изменения в таблицах обмена (для УРБД), обновляет индексы и пишет в журнал транзакций. Если записей десятки или сотни тысяч, это может занять часы. Давайте рассмотрим альтернативные варианты, которые позволяют решить задачу за секунды или минуты.
В ходе обсуждения проблемы участники предложили использовать команду SQL TRUNCATE TABLE. Это самый быстрый способ очистки таблицы. Он работает практически мгновенно, так как не логирует удаление каждой строки отдельно, а просто освобождает страницы данных.
Для выполнения этого действия необходимо знать физическое имя таблицы справочника в базе данных SQL (обычно это имена вида SC..., например SC552). Найти соответствие можно в файле словаря данных 1Cv7.DD или используя специальные утилиты.
Запрос выглядит следующим образом:
TRUNCATE TABLE SC552
Преимущества:
Серьезные недостатки и риски:
Несмотря на то, что этот метод сработал у автора вопроса, мы обязаны предупредить о скрытых проблемах, которые не всегда очевидны сразу:
TRUNCATE удаляет записи физически без проверки ссылок. Если на удаленные элементы ссылаются документы или другие справочники, в базе появятся "битые ссылки" (знаменитые <Объект не найден...>).1SCONST. При использовании TRUNCATE основной таблицы справочника, записи в 1SCONST остаются. Это приводит к накоплению "мертвых" данных, которые привязаны к несуществующим ID.TRUNCATE не регистрирует изменения в системной таблице _1SUPDTS. Периферийные базы "не узнают", что данные были удалены, что приведет к рассинхронизации.Более классический подход в SQL — использование оператора DELETE. Посмотрим на отличия:
DELETE FROM SC552
В отличие от TRUNCATE, эта операция полностью протоколируется. Если таблица огромная, лог транзакций может вырасти до критических размеров. Кроме того, DELETE также не очищает таблицу 1SCONST и не регистрирует изменения для УРБД автоматически.
Давайте проанализируем наиболее сбалансированное решение, которое сочетает скорость SQL и безопасность штатных механизмов 1С. Суть метода заключается в массовой установке пометки удаления через прямой запрос SQL, с последующим штатным удалением.
Шаг 1: Массовая пометка на удаление через SQL
Вместо физического удаления, мы используем команду UPDATE, чтобы установить флаг пометки удаления (поле ISMARK) в значение 1. Это происходит очень быстро.
Пример запроса:
UPDATE SC552
SET ISMARK = 1
WHERE ISMARK = 0 -- Помечаем только те, что еще не помечены
Если необходимо установить пометку удаления не для всех, а по условию, можно добавить фильтрацию:
UPDATE SC552
SET ISMARK = 1
FROM SC552
WHERE SC552.DESCR LIKE '%Удалить%'
Шаг 2: Штатное удаление помеченных объектов
После выполнения SQL-запроса мы заходим в 1С в монопольном режиме и запускаем стандартную обработку "Удаление помеченных объектов".
Почему это правильно:
Если ваша база данных участвует в обмене, обратите особое внимание на тот факт, что прямые запросы (SQL) идут в обход механизмов регистрации изменений 1С. Таблица регистрации изменений называется _1SUPDTS.
Если вы "грохнули" записи через TRUNCATE или DELETE в центральной базе:
В случае использования УРБД, гибридный метод (SQL Update IsMark + Штатное удаление) является единственно верным безопасным путем, так как он задействует стандартные механизмы удаления, которые "знают" об обмене.
Если вы все же решили использовать DELETE или массовую вставку/удаление, давайте разберем, какие регламентные операции на SQL Server необходимо выполнить для поддержания здоровья базы:
DELETE сильно фрагментирует индексы. Их необходимо перестроить. TRUNCATE в этом плане лучше, так как он сбрасывает индексы, но, как мы выяснили, он опасен по другим причинам.Чтобы не искать имена таблиц (типа SC552) вручную в файле DD, можно использовать внешнюю компоненту 1С++ и класс MetaDataWork. Это позволяет писать универсальный код.
Пример логики кода на 1С с использованием прямых запросов:
ТекстЗапроса = "
|UPDATE " + MetaDataWork.ПолучитьИмяТаблицыСправочника("Номенклатура") + "
|SET ISMARK = 1
|WHERE ISMARK = 0
|";
Такой подход позволяет автоматизировать процесс пометки удаления, сохраняя при этом гибкость кода и независимость от конкретной структуры базы данных (которая может меняться после обновлений конфигурации).
Подведем итог. Для быстрого удаления записей:
TRUNCATE.