Многие разработчики 1С рано или поздно задаются вопросом: почему выполнение команды DELETE в консоли SQL Server происходит почти мгновенно, в то время как аналогичное удаление объектов через встроенный язык 1С может занимать минуты или даже часы? Кажется, что в обоих случаях выполняется одна и та же команда, но на деле «под капотом» 1С происходит огромный объем скрытой работы. Разберем по шагам, из чего складывается эта разница и какие механизмы платформы замедляют процесс.
Проанализируем базовый механизм обеспечения надежности данных. Когда мы удаляем объект в 1С (например, элемент справочника или документ), платформа обязана гарантировать, что в базе не останется «битых» ссылок. В классических реляционных базах данных это решается на уровне FOREIGN KEY, однако в 1С связи между таблицами логические.
При вызове метода Удалить() или интерактивном удалении платформа генерирует десятки и сотни поисковых запросов ко всем таблицам метаданных, где данный тип объекта может быть использован. Если база содержит тысячи таблиц, проверка одной ссылки превращается в колоссальную нагрузку. Прямой SQL-запрос игнорирует эти правила, просто вырезая строку из таблицы, что и дает основной прирост скорости, но ценой потенциального нарушения логики базы.
Выясним, что происходит на уровне сервера приложений. 1С — это не просто надстройка над SQL, это объектно-ориентированная среда. При удалении объекта происходят следующие действия:
ПередУдалением или ПриУдалении). В этих процедурах может быть написана сложная бизнес-логика, дополнительные проверки или каскадное удаление связанных записей.При прямом обращении к SQL вся эта логика полностью обходится. Никакие подписки на события не срабатывают, а модули объектов не компилируются.
Рассмотрим разницу в записи логов. При удалении через 1С каждый объект обычно обрабатывается в рамках отдельной транзакции (если это не массовая обработка в одном блоке). Это заставляет SQL Server постоянно фиксировать изменения в файле лога транзакций (.ldf).
Более того, если мы удаляем объект с табличными частями, 1С выполняет отдельный запрос DELETE FROM... для каждой табличной части и каждой записи в ней. Посмотрим на пример: если у документа 5 табличных частей, платформа выполнит минимум 6 SQL-запросов (1 для заголовка и 5 для таблиц). Прямой SQL позволяет удалить всё одним набором команд или даже использовать TRUNCATE (если нужно очистить таблицу целиком), что практически не нагружает лог транзакций.
Разберем ситуацию с регистрами, которая часто упоминалась в обсуждении. Существует два принципиально разных подхода к удалению записей в 1С:
МенеджерЗаписи.Удалить(). Платформа порождает запрос с условием WHERE, перечисляющим все ключевые поля. Для 1000 записей — это 1000 запросов.РегистрСведенийНаборЗаписей, устанавливаем отбор и записываем пустой набор.Даже во втором случае 1С ведет себя «осторожно». Перед тем как выполнить удаление, она может выполнить SELECT, чтобы сравнить старые данные с новыми. Рассмотрим пример кода:
Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(ВыбНоменклатура);
Набор.Записать(); // Здесь происходит удаление
Платформа гарантирует, что в момент Набор.Записать() будут учтены все блокировки и актуальное состояние данных. SQL-запрос же просто выполнит команду без предварительного анализа состава данных.
Проанализируем влияние прав доступа. Если в конфигурации настроены ограничения на уровне записей (RLS), любой запрос 1С на удаление динамически модифицируется. К вашему простому запросу платформа «приклеивает» сложные вложенные подзапросы для проверки прав текущего пользователя. Это превращает один DELETE в тяжелую аналитическую операцию. Прямой SQL-запрос от имени администратора БД эти проверки игнорирует.
Важным аспектом является поддержание актуальности индексов и таблиц итогов. В 1С при удалении движений по регистрам накопления или бухгалтерии система автоматически пересчитывает итоги (агрегаты). Это требует дополнительных операций записи. При массовом удалении через SQL индексы могут фрагментироваться, а таблицы итогов и вовсе станут невалидными, так как данные в основной таблице исчезли, а в таблице итогов — остались.
Подводя итог, можно сказать, что удаление через SQL быстрее, потому что оно «не информированное». Оно не знает о ссылках, о правах, об итогах и о бизнес-логике. Платформа 1С тратит время на то, чтобы сохранить базу в целостном и рабочем состоянии.
Когда стоит использовать SQL:
Когда НЕЛЬЗЯ использовать SQL:
Для ускорения удаления средствами 1С рекомендуется использовать НаборЗаписей с установленным свойством ОбменДанными.Загрузка = Истина, что позволяет отключить часть проверок и обработчиков, сохраняя при этом относительную безопасность операции.