Регистры накопления и сведений в 1С:Предприятие 8.3 — это основа аналитики и корректной работы системы. Со временем они заполняются устаревшими данными, дублями или ошибочными записями, что приводит к замедлению работы, ошибкам в отчётах и даже блокировке транзакций. Автоматические механизмы (например, регламентные задания) не всегда справляются с глубокой очисткой, особенно если речь идёт о критических регистрах вроде РегистрНакопления.ПартииТоваров или РегистрСведений.ЦеныНоменклатуры.
Вручную чистить регистры приходится в трёх случаях: после неудачного обмена данными, при миграции с устаревшей конфигурации или когда базу «замусорили» тестовые операции. Но здесь кроется главная опасность: неправильный SQL-запрос или удаление без транзакции может разрушить ссылки между объектами, сделав базу неработоспособной. Эта статья поможет избежать типичных ошибок и провести очистку с минимальными рисками.
Прежде чем приступать, убедитесь, что у вас есть:
- 🔹 Полная резервная копия базы (не только через 1С, но и на уровне SQL-сервера).
- 🔹 Права администратора на сервере 1С и доступ к SQL Management Studio (для MS SQL) или pgAdmin (для PostgreSQL).
- 🔹 Тестовая копия базы для отработки запросов (обязательно!).
- 🔹 Понимание структуры регистра: какие измерения, ресурсы и реквизиты в нём хранятся.
1. Когда ручная очистка регистров действительно необходима
Не каждая проблема с регистрами требует ручного вмешательства. Например, если в отчёте Ведомость по товарам отображаются устаревшие остатки, сначала проверьте настройки отбора или актуальность проведения документов. Ручное удаление оправдано в четырёх сценариях:
1. После некорректного обмена данными (например, через Универсальный формат обмена или CommerceML), когда в регистрах появились записи без связей с реальными документами. Типичный признак — ошибка вида "Не найден объект ссылочного типа (Документ.ПоступлениеТоваровУслуг, Ссылка=...)">.
2. При миграции с устаревших версий (например, с 1С 7.7 или 1С 8.1), когда старые данные переносятся без привязки к новой структуре. В этом случае регистры могут содержать записи с несуществующими измерениями.
3. После массового тестирования, когда в базу добавили тысячи тестовых документов, а стандартное удаление через Пометить на удаление не сработало из-за ссылочной целостности.
4. Для оптимизации производительности, если регистр разросся до миллионов записей (например, РегистрНакопления.ВзаиморасчетыСКонтрагентами), и индексы перестали справляться с нагрузкой.
⚠️ Внимание: Если проблема вызвана ошибкой в коде конфигурации (например, бесконечным циклом записи в регистр), очистка не поможет — нужно исправлять алгоритм в модулях объектов.
2. Подготовка к очистке: резервное копирование и анализ структуры
Первый шаг — создать резервную копию базы на уровне SQL-сервера. В MS SQL это делается через Tasks → Back Up, в PostgreSQL — командой pg_dump. Важно: копия через 1С:Предприятие → Администрирование → Выгрузить информационную базу не подходит — она не восстановит данные при повреждении таблиц.
Далее проанализируйте структуру целевого регистра. Например, для РегистрНакопления.ОстаткиТоваров выполните запрос:
SELECT *
FROM InformationRegister_OstatkiTovarov
WHERE [Период] BETWEEN '2023-01-01' AND '2023-12-31'
Обратите внимание на:
- 📌 Ключевые поля (обычно
Период,Регистратор, измерения вродеНоменклатураилиСклад). - 📌 Ссылочную целостность: есть ли в таблице поля с ссылками на документы (например,
СсылкаНаДокумент). - 📌 Объём данных: если записей больше 100 тыс., удаление займёт много времени и может заблокировать базу.
Для регистров сведений (например, РегистрСведений.ЦеныНоменклатуры) проверьте, есть ли зависимости от других регистров или справочников. Например, цены могут использоваться в документах ЗаказКлиента — их удаление приведёт к ошибкам при проведении.
Изучить структуру регистра в конфигураторе (раздел "Объекты метаданных")|
Проверить наличие ссылок на регистр в других объектах (через "Поиск ссылок")|
Создать тестовую копию базы для экспериментов|
Подготовить SQL-скрипты с условием WHERE (никогда не использовать DELETE без фильтра!)|
Уведомить пользователей о времени простоя базы-->
3. Методы очистки: от простого к сложному
Существует три основных способа ручной очистки регистров в 1С 8.3, отличающихся по безопасности и скорости. Выбор зависит от объёма данных и критичности регистра:
1. Через конфигуратор (самый безопасный, но медленный)
Подходит для небольших регистров (до 10 тыс. записей). Откройте конфигуратор, перейдите в Администрирование → Тестирование и исправление и выберите Поиск и удаление помеченных объектов. Однако этот метод не удалит записи, на которые есть ссылки из документов.
2. SQL-запросы (быстро, но рискованно)
Используйте только если уверены в структуре таблиц. Пример запроса для очистки регистра накопления по периоду:
BEGIN TRANSACTION;
DELETE FROM AccumulationRegister_OstatkiTovarov
WHERE Период < '2023-01-01';
-- Проверяем количество удалённых строк
SELECT @@ROWCOUNT AS 'Удалённых записей';
-- Если всё корректно, подтверждаем транзакцию
COMMIT TRANSACTION;
3. Специальные обработки (оптимальный баланс)
В 1С есть встроенные обработки для работы с регистрами, например, УниверсальнаяОбработкаРаботыСРегистрами.epf. Она позволяет удалять записи с учётом ссылочной целостности. Скачать её можно из каталога 1С:ИТС или форумов разработчиков.
| Метод | Скорость | Безопасность | Когда использовать |
|---|---|---|---|
| Через конфигуратор | Низкая | Высокая | Небольшие регистры, нет ссылок на документы |
| SQL-запросы | Высокая | Низкая | Крупные регистры, опыт работы с SQL |
| Специальные обработки | Средняя | Средняя | Регистры со сложной структурой, нужна проверка ссылок |
⚠️ Внимание: При использовании SQL-запросов на PostgreSQL синтаксис отличается. Например, вместо@@ROWCOUNTиспользуйтеRETURNING *. Всегда тестируйте запросы на копии базы!
4. Пошаговая инструкция: очистка регистра накопления
Рассмотрим процесс на примере регистра РегистрНакопления.ОстаткиТоваров. Предположим, нужно удалить все записи старше 2022 года.
Шаг 1. Определяем таблицу в SQL
В MS SQL регистры накопления хранятся в таблицах с префиксом AccumulationRegister_. Для нашего примера это AccumulationRegister_OstatkiTovarov. Уточните имя через запрос:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'AccumulationRegister_Ostatki%'
Шаг 2. Формируем запрос с фильтром
Важно указать точные условия, чтобы не удалить актуальные данные. Например, для удаления записей по периоду и складу:
DELETE FROM AccumulationRegister_OstatkiTovarov
WHERE Период < '2022-01-01'
AND Склад IN (
SELECT _IDRRef
FROM _Reference16 -- Таблица справочника "Склады"
WHERE Description = 'Основной склад'
)
Шаг 3. Проверяем ссылки перед удалением
Убедитесь, что на удаляемые записи нет ссылок из документов. Для этого выполните:
SELECT COUNT(*)
FROM Document_ПоступлениеТоваровУслуг AS d
WHERE EXISTS (
SELECT 1
FROM AccumulationRegister_OstatkiTovarov AS r
WHERE r.Регистратор = d._IDRRef
AND r.Период < '2022-01-01'
)
Если результат > 0, удаление приведёт к ошибкам при открытии документов.
Шаг 4. Выполняем удаление в транзакции
Всегда оборачивайте DELETE в транзакцию, чтобы можно было откатить изменения при ошибке:
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM AccumulationRegister_OstatkiTovarov
WHERE Период < '2022-01-01';
-- Ждём 5 секунд (для больших таблиц)
WAITFOR DELAY '00:00:05';
COMMIT TRANSACTION;
PRINT 'Удаление завершено успешно';
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
PRINT 'Ошибка: ' + ERROR_MESSAGE();
END CATCH
Если регистр очень большой (более 1 млн записей), разбивайте удаление на порции по 10-50 тыс. записей за раз, чтобы избежать блокировки базы. Используйте конструкцию WHERE ID IN (SELECT TOP 10000 ID FROM Таблица WHERE Условие)
5. Очистка регистров сведений: особенности и риски
Регистры сведений (например, РегистрСведений.ЦеныНоменклатуры) хранят данные без привязки к периодам, но часто имеют сложные измерения. Их очистка требует дополнительных проверок:
1. Проверка зависимостей
Цены могут использоваться в документах РеализацияТоваровУслуг или ЗаказКлиента. Удаление актуальных цен приведёт к ошибкам при проведении. Чтобы найти зависимости, выполните:
SELECT DISTINCT d.Description
FROM Document_РеализацияТоваровУслуг AS d
JOIN Document_РеализацияТоваровУслуг_Tables AS t ON d._IDRRef = t._Document_IDRRef
JOIN InformationRegister_CenyNomenklatury AS r ON t.Цена = r._IDRRef
WHERE r.ПериодДействия > GETDATE()
2. Использование обработки "Универсальная очистка"
Для регистров сведений лучше использовать специализированные обработки, например, ОчисткаРегистровСведений.epf. Она позволяет:
- 🔸 Удалять записи по нескольким измерениям одновременно.
- 🔸 Проверять ссылки перед удалением.
- 🔸 Вести лог изменений.
3. Альтернатива: пометка на удаление
Если записи связаны с документами, вместо физического удаления пометьте их на удаление через 1С:
// В модуле внешней обработки
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрСведений.ЦеныНоменклатуры КАК Регистр
|ГДЕ
| Регистр.ПериодДействия < &ДатаГраница";
Запрос.УстановитьПараметр("ДатаГраница", НачалоДня(ТекущаяДата()));
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Регистр = Выборка.Регистр;
Регистр.УстановитьПометкуУдаления(Истина);
Регистр.Записать();
КонецЦикла;
⚠️ Внимание: В регистрах сведений с независимым записью (например, РегистрСведений.НастройкиПользователей) удаление одной записи не влияет на другие. А в регистрах с подчинением (например, цены номенклатуры) удаление "головной" записи удалит все подчинённые.
6. Восстановление после ошибок и оптимизация
Если после очистки база ведёт себя нестабильно (например, выдаёт ошибки вида "Нарушена ссылочная целостность"), выполните следующие шаги:
1. Проверка целостности
В конфигураторе запустите Администрирование → Тестирование и исправление с флагами:
- 🔹 Реиндексация таблиц (устраняет проблемы с индексами).
- 🔹 Проверка логической целостности (ищет "битые" ссылки).
- 🔹 Проверка ссылочной целостности (критично для регистров).
2. Обновление статистики SQL
После массового удаления статистика запросов устаревает. В MS SQL выполните:
EXEC sp_updatestats;
DBCC FREEPROCCACHE;
В PostgreSQL:
ANALYZE VERBOSE;
3. Пересчёт итогов регистров
Если очищался регистр накопления, пересчитайте итоги через конфигуратор:
// В внешней обработке
ПересчетИтогов = Новый ПересчетИтоговРегистровНакопления;
ПересчетИтогов.ДобавитьРегистр(Метаданные.РегистрыНакопления.ОстаткиТоваров);
ПересчетИтогов.ВыполнитьПересчет();
4. Оптимизация производительности
После очистки крупных регистров:
- 🔹 Пересоздайте индексы (в SQL Management Studio правой кнопкой по таблице →
Reindex). - 🔹 Настройте
Автосжатиедля таблиц регистров. - 🔹 Проверьте планы выполнения медленных запросов (используйте
EXPLAIN ANALYZEв PostgreSQL).
После любой массовой очистки регистров обязательно перезапустите сервер 1С:Предприятие и кластер серверов 1С (если используется). Это сбросит кэш метаданных и предотвратит ошибки доступа.
7. Типичные ошибки и как их избежать
Даже опытные администраторы допускают ошибки при ручной очистке. Вот самые распространённые и способы их предотвращения:
1. Удаление без транзакции
Если не использовать BEGIN TRANSACTION, при сбое (например, отключении электричества) база останется в неконсистентном состоянии. Всегда проверяйте результат через SELECT @@ROWCOUNT перед COMMIT.
2. Игнорирование триггеров
В 1С на регистры могут быть навешаны триггеры (например, для аудита изменений). При прямом SQL-удалении они не срабатывают, что приводит к расхождению данных. Проверьте наличие триггеров через:
SELECT * FROM sys.triggers
WHERE parent_id = OBJECT_ID('AccumulationRegister_OstatkiTovarov')
3. Неучтённые связи с другими регистрами
Некоторые регистры связаны между собой. Например, РегистрНакопления.ПартииТоваров может ссылаться на РегистрСведений.СерийныеНомера. Удаление из одного без очистки другого приведёт к ошибкам. Всегда анализируйте структуру через Поиск ссылок в конфигураторе.
4. Очистка без учёта периодов
В регистрах накопления период — ключевое поле. Если удалить записи за текущий период, итоги станут некорректными. Всегда фильтруйте по дате:
WHERE Период < DATEADD(month, -6, GETDATE()) -- Удаляем данные старше 6 месяцев
5. Работа без тестовой копии
Даже если вы уверены в запросе, всегда тестируйте его на копии базы. Для создания тестовой копии в PostgreSQL используйте:
CREATE DATABASE test_db TEMPLATE production_db;
Что делать, если после очистки 1С не запускается?
Если после удаления записей база не открывается или выдаёт ошибку "Не найден объект метаданных", попробуйте:
1. Восстановить базу из резервной копии.
2. Запустить 1С в режиме конфигуратора с ключом /RepairDBCheck.
3. Если ошибка связана с отсутствием ссылок, используйте обработку ПоискИИсправлениеСсылок.epf из каталога ИТС.
4. В крайнем случае обратитесь в поддержку 1С с логами ошибок (папка %APPDATA%\1C\1Cv8\logs).
FAQ: Частые вопросы по очистке регистров
Можно ли очистить регистр без доступа к SQL-серверу?
Да, но с ограничениями. В конфигураторе можно использовать Запрос.Выполнить() с конструкцией УДАЛИТЬ на языке 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"УДАЛИТЬ ИЗ РегистрНакопления.ОстаткиТоваров
ГДЕ Период < &ДатаГраница";
Запрос.УстановитьПараметр("ДатаГраница", '20220101');
Запрос.Выполнить();
Однако этот метод медленнее SQL и не подходит для крупных регистров (более 50 тыс. записей).
Как очистить регистр, если на него есть ссылки из документов?
Есть три варианта:
- Удалить или перепровести документы, ссылающиеся на регистр.
- Использовать пометку на удаление (если ссылки некритичны).
- Перенести актуальные данные в новый регистр через обработку, а старый очистить полностью.
Для анализа ссылок используйте запрос:
SELECT DISTINCT d._Description AS Документ
FROM _DocumentXXX AS d
JOIN AccumulationRegister_OstatkiTovarov AS r ON d._IDRRef = r.Регистратор
WHERE r.Период < '2022-01-01'
Сколько времени занимает очистка регистра с 1 млн записей?
Время зависит от:
- 🔹 Типа СУБД: MS SQL справится за 10-30 минут, PostgreSQL — за 5-15 минут.
- 🔹 Индексов: если индексы фрагментированы, время увеличится.
- 🔹 Нагрузки на сервер: в рабочее время очистка может заблокировать других пользователей.
Рекомендуется выполнять очистку в нерабочие часы и разбивать её на порции по 50-100 тыс. записей.
Можно ли очистить регистр частично, оставив только актуальные данные?
Да, для этого используйте WHERE с точными условиями. Например, чтобы оставить только данные по одному складу:
DELETE FROM AccumulationRegister_OstatkiTovarov
WHERE Склад NOT IN (
SELECT _IDRRef
FROM _Reference16
WHERE Description = 'Основной склад'
)
Для регистров сведений (например, цен) можно оставить только актуальные записи:
DELETE FROM InformationRegister_CenyNomenklatury
WHERE ПериодДействия < GETDATE()
Что делать, если после очистки неверно считаются остатки?
Это означает, что были удалены записи, влияющие на итоги. Восстановите остатки через:
- Перепроведите все документы, затрагивающие регистр (через
Обработка.ПерепровдениеДокументов). - Выполните пересчёт итогов (см. раздел 6).
- Если проблема остаётся, восстановите данные из резервной копии и повторите очистку с более жёсткими фильтрами.