Как эффективно найти и удалить неиспользуемую номенклатуру, игнорируя записи в регистре «Коды товаров SKU»?

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

При работе с крупными базами данных, такими как 1С:Розница 2.3, часто возникает необходимость очистки справочника номенклатуры от «мусорных» записей. Основная сложность заключается в том, что стандартные механизмы контроля ссылочной целостности не позволяют удалить объект, если на него есть хотя бы одна ссылка. В типовых конфигурациях практически каждый элемент номенклатуры автоматически обрастает техническими записями в регистрах сведений (например, штрихкоды, коды SKU), что делает стандартное удаление невозможным без предварительной подготовки. Разберем, как автоматизировать этот процесс, не дожидаясь окончания работы стандартных функций часами.

Анализ проблемы производительности функции НайтиПоСсылкам

Рассмотрим ситуацию: у нас есть около 4000 объектов номенклатуры, которые нужно проверить на наличие «реальных» ссылок (в документах поступления, реализации или остатках). Использование стандартного метода НайтиПоСсылкам в лоб для такого количества объектов приводит к катастрофическому падению производительности. Выясним причину: этот метод выполняет поиск по абсолютно всем таблицам базы данных, которые могут содержать ссылки на данный тип объекта. Он не останавливается, когда находит первую ссылку, а продолжает собирать полную статистику вхождений, что в нашем случае избыточно.

Решение №1: Использование параметров исключения в стандартной функции

Если нам известно, что записи в регистре сведений Коды товаров SKU не представляют ценности при удалении (их можно очистить программно), мы можем исключить этот регистр из области поиска. Рассмотрим программный код, который позволяет сформировать массив исключений. Проанализируем, как можно динамически собрать список всех метаданных и исключить только нужный нам регистр:


СписИмен = Новый СписокЗначений;
СписИмен.Добавить("Документы");
СписИмен.Добавить("Справочники");
СписИмен.Добавить("РегистрыСведений");

Исключить = "РегистрСведений.КодыТоваровSKU"; // Уточните имя в вашей конфигурации
МассивИсключений = Новый Массив;

Для Каждого Мет из СписИмен Цикл
    ИмяКоллекции = Мет.Значение;
    Для Каждого ВидМета из Метаданные[ИмяКоллекции] Цикл
        Если ВидМета.ПолноеИмя() = Исключить Тогда
            Продолжить;
        Иначе
            // В некоторых случаях полезно добавить проверку на наличие реквизита типа Номенклатура
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

// Теперь вызываем поиск, передав массив исключений четвертым параметром
ТаблицаСсылок = НайтиПоСсылкам(МассивНоменклатуры, , , МассивИсключений);

Этот способ значительно сократит объем обрабатываемых данных, однако функция всё равно будет просматривать все остальные таблицы до самого конца. Для 4000 позиций это может занять очень много времени.

Решение №2: Проверка актуальности по движениям (бизнес-логика)

Посмотрим на задачу под другим углом. Объект номенклатуры имеет информационную ценность только в том случае, если по нему были реальные движения. Проанализируем состояние склада. Если по позиции нет остатков в регистре накопления ТоварыНаСкладах и отсутствуют записи в регистрах продаж или закупок за последний год, такая номенклатура, скорее всего, является кандидатом на удаление, даже если на нее ссылаются цены или сегменты.

Вместо поиска ссылок по всей базе, мы можем сначала выполнить быстрый запрос к регистрам накопления. Если движений нет, мы переходим к следующему этапу проверки ссылок, что отсеет значительную часть «активной» номенклатуры еще на старте.

Решение №3: Оптимизированный ручной обход метаданных с прерыванием

Для достижения максимальной скорости работы, особенно когда объектов тысячи, мы рекомендуем отказаться от НайтиПоСсылкам в пользу прямого обхода метаданных через запросы. Главный секрет оптимизации здесь — принцип первого вхождения. Нам не нужно знать, сколько раз номенклатура упоминается в документах; нам достаточно узнать, что она упоминается хотя бы один раз.

Разберем алгоритм по шагам:

  1. Получаем список всех метаданных, где есть реквизиты с типом СправочникСсылка.Номенклатура.
  2. Для каждого объекта номенклатуры из нашего списка запускаем цикл по этим таблицам.
  3. Внутри цикла выполняем максимально легкий запрос: ВЫБРАТЬ ПЕРВЫЕ 1.
  4. Если запрос вернул результат — прерываем поиск для этой позиции (команда Прервать) и помечаем ее как «неудаляемую».

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


Для Каждого ТекНоменклатура Из СписокДляПроверки Цикл
    ЕстьСсылки = Ложь;
    Для Каждого ТаблицаМетаданных Из СписокТаблицДляПоиска Цикл
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ " + ТаблицаМетаданных + " ГДЕ Номенклатура = &Номенклатура";
        Запрос.УстановитьПараметр("Номенклатура", ТекНоменклатура);
        
        Если НЕ Запрос.Выполнить().Пустой() Тогда
            ЕстьСсылки = Истина;
            Прервать; // Ссылка найдена, дальше искать по этой номенклатуре нет смысла
        КонецЕсли;
    КонецЦикла;
    
    Если НЕ ЕстьСсылки Тогда
        // Здесь можно программно удалить записи из Коды SKU и пометить на удаление саму номенклатуру
    КонецЕсли;
КонецЦикла;

Важные замечания по работе с регистром «Коды товаров SKU»

Проанализируем специфику регистра КодыТоваровSKU. В конфигурации «Розница» этот регистр часто используется для связи с торговым оборудованием и внешними системами (например, Эвотор). Важный момент: перед тем как окончательно удалять номенклатуру, записи в этом регистре нужно очистить. Сделать это лучше всего через набор записей с установленным отбором по номенклатуре:


Набор = РегистрыСведений.КодыТоваровSKU.СоздатьНаборЗаписей();
Набор.Отбор.Номенклатура.Установить(ОбъектНоменклатуры);
Набор.Записать(); // Записываем пустой набор, тем самым удаляя связи

Только после этого объект можно будет удалить физически или пометить на удаление без возникновения ошибок целостности. Также стоит учитывать планы обмена. Если ваша номенклатура зарегистрирована к обмену с другими базами, удаление ссылки может привести к ошибкам в узлах обмена. Перед массовой очисткой убедитесь, что регистрация изменений по этим объектам также удалена.

Подводя итог, отметим, что для 4000 объектов наиболее эффективным будет комбинированный метод: сначала отсеиваем номенклатуру с остатками через быстрый запрос, затем проводим оптимизированный ручной поиск ссылок с прерыванием цикла, исключая технические регистры.

← На главную