Сколько места освободит свёртка базы 1С: как посчитать до начала работ
Иван Недомолков · Chop etilgan:
Решение о свёртке почти всегда принимают по одному числу: размеру базы. Терабайт, бэкап не укладывается в ночь, значит, сворачиваем и оставляем три года. Сколько это освободит, выясняется только после недели подготовки и ночного окна.
Ответ можно получить заранее, и для этого не нужен ни тестовый прогон свёртки, ни копия базы. Достаточно разделить вес базы на две части: ту, что свёртка режет по дате, и ту, которую она не трогает. Ниже порядок такого расчёта, код для него и места, где цифра расходится с жизнью.
Шаг 1. Разделить объекты на режущиеся и нережущиеся
Типовая свёртка удаляет документы старше границы и движения регистров с периодом раньше неё, оставляя остатки на дату среза. Всё остальное она не трогает:
| Вид объекта | Поле, по которому режет свёртка | Что происходит |
|---|---|---|
| документ | Дата | старые удаляются |
| регистр накопления, бухгалтерии | Период | старые движения сворачиваются в остатки |
| периодический регистр сведений | Период | старые записи уходят, срез последних остаётся |
| непериодический регистр сведений | нет | остаётся целиком |
| справочник | нет | остаётся целиком |
| версии объектов, служебные кэши | своя дата или вовсе без неё | остаются, у них своя очистка или никакой |
Посмотрите, сколько в типовой конфигурации объектов из нижней половины таблицы. Мы пересчитали Управление торговлей 11.5.22.67: 281 документ, 101 регистр накопления, 806 регистров сведений, из них 729 без периода и без регистратора (непериодические, с независимой записью), и 486 справочников. Версии объектов тоже живут в регистре без периода: измерения “Объект” и “НомерВерсии”, дата хранится в реквизите “ДатаВерсии”.
Это число объектов, а не вес. Сколько из этих 729 регистров что-то весят, зависит от базы, и проверять надо на своей.
Шаг 2. Оценить каждый режущийся объект
Правило простое. Объект с датой отдаст при свёртке примерно ту долю своего места, какую составляют записи старше границы. Объект без даты не отдаст ничего.
Размер объекта платформа возвращает методом ПолучитьРазмерДанныхБазыДанных, количество записей по годам считает обычный запрос. Функция ниже сама определяет, по какому полю резать объект, и для объекта без даты возвращает Неопределено. Запускать её на сервере и под полными правами: при ограничении доступа на уровне записей запрос увидит только разрешённые строки или упадёт.
// Оценка того, сколько места освободит свёртка у одного объекта.
// ПолноеИмя - "Документ.РеализацияТоваровУслуг", "РегистрНакопления.ТоварыНаСкладах" и т.п.
// ГраницаСреза - записи раньше этой даты считаем уходящими.
// Возвращает Неопределено, если у объекта нет даты, по которой режет свёртка.
Функция ОценкаСвертки(ПолноеИмя, ГраницаСреза) Экспорт
ОбъектМД = Метаданные.НайтиПоПолномуИмени(ПолноеИмя);
Если ОбъектМД = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
// Документы режем по дате, движения регистров по периоду.
// Непериодические регистры сведений, справочники и регистры расчёта сюда не попадают.
Если Метаданные.Документы.Содержит(ОбъектМД) Тогда
ПолеДаты = "Дата";
ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМД)
Или Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМД)
Или Метаданные.РегистрыСведений.Содержит(ОбъектМД)
И ОбъектМД.ПериодичностьРегистраСведений
<> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
ПолеДаты = "Период";
Иначе
Возврат Неопределено;
КонецЕсли;
// Размер в байтах, вместе с табличными частями и индексами объекта.
ИменаОбъектов = Новый Массив;
ИменаОбъектов.Добавить(ПолноеИмя);
Размер = ПолучитьРазмерДанныхБазыДанных(, ИменаОбъектов);
// Старые записи считаем по точной дате границы, а разбивку по годам
// выгружаем отдельно: по ней видно, сколько лет истории лежит в объекте.
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Граница", ГраницаСреза);
Запрос.Текст = СтрШаблон(
"ВЫБРАТЬ
| ГОД(Т.%2) КАК Год,
| КОЛИЧЕСТВО(*) КАК Записей,
| СУММА(ВЫБОР КОГДА Т.%2 < &Граница ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) КАК Старых
|ИЗ
| %1 КАК Т
|СГРУППИРОВАТЬ ПО
| ГОД(Т.%2)
|УПОРЯДОЧИТЬ ПО
| Год", ПолноеИмя, ПолеДаты);
ПоГодам = Запрос.Выполнить().Выгрузить();
Всего = ПоГодам.Итог("Записей");
Старых = ПоГодам.Итог("Старых");
Результат = Новый Структура;
Результат.Вставить("Размер", Размер);
Результат.Вставить("Записей", Всего);
Результат.Вставить("Старых", Старых);
Результат.Вставить("Уйдет", ?(Всего = 0, 0, Размер * Старых / Всего));
Результат.Вставить("ПоГодам", ПоГодам);
Возврат Результат;
КонецФункции
На тестовой УТ 11.5.22.67 функция для регистра остатков товаров, периодического регистра цен и документа реализации вернула размер, число записей и долю старых, а для версий объектов и справочника номенклатуры вернула Неопределено. Чисел с той базы не приводим: истории в ней меньше года, и оценка свёртки на ней ничего не значит.
Учтите нагрузку. Группировка по году читает регистр целиком, и на сотнях миллионов строк это заметно. На рабочей базе такой запрос лучше запускать ночью или на копии.
Шаг 3. Сводка по всей конфигурации
Объектов сотни, поэтому вручную их не перебрать. Цикл по метаданным собирает таблицу “объект, размер, сколько уйдёт”. Справочники в него включены нарочно: они попадут в сводку с нулём в колонке “Уйдет”, и их вес окажется рядом со всем остальным, а не за кадром.
// Сводка: сколько весит каждый объект и сколько из этого уйдёт при свёртке.
// Срез "текущий год и два прошлых".
ГраницаСреза = Дата(Год(ТекущаяДатаСеанса()) - 2, 1, 1);
Сводка = Новый ТаблицаЗначений;
Сводка.Колонки.Добавить("Объект");
Сводка.Колонки.Добавить("Размер");
Сводка.Колонки.Добавить("Уйдет");
Коллекции = Новый Массив;
Коллекции.Добавить(Метаданные.Документы);
Коллекции.Добавить(Метаданные.РегистрыНакопления);
Коллекции.Добавить(Метаданные.РегистрыБухгалтерии);
Коллекции.Добавить(Метаданные.РегистрыСведений);
Коллекции.Добавить(Метаданные.Справочники);
Для Каждого Коллекция Из Коллекции Цикл
Для Каждого ОбъектМД Из Коллекция Цикл
ПолноеИмя = ОбъектМД.ПолноеИмя();
Строка = Сводка.Добавить();
Строка.Объект = ПолноеИмя;
Оценка = ОценкаСвертки(ПолноеИмя, ГраницаСреза);
Если Оценка = Неопределено Тогда
// Объект без даты: весит, но свёрткой не уменьшится.
ИменаОбъектов = Новый Массив;
ИменаОбъектов.Добавить(ПолноеИмя);
Строка.Размер = ПолучитьРазмерДанныхБазыДанных(, ИменаОбъектов);
Строка.Уйдет = 0;
Иначе
Строка.Размер = Оценка.Размер;
Строка.Уйдет = Оценка.Уйдет;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Сводка.Сортировать("Размер Убыв");
Читать результат надо так. Сумма колонки “Уйдет”, делённая на сумму “Размер”, и есть ожидаемый эффект свёртки. Первые двадцать строк по размеру показывают, где лежит вес. Если наверху версии объектов или регистры без периода, свёртку планировать рано: сначала разбираться с ними.
Шаг 4. Поправить цифру
Расчёт пропорциональный, и у него есть систематические сдвиги. Почти все они в одну сторону, расчёт завышает:
- Старые документы бывают короче. Если раньше в табличных частях было меньше строк, доля по числу документов больше доли по месту.
- Срез последних у периодических регистров сведений остаётся. Актуальные значения на дату среза свёртка сохраняет, освобождается меньше.
- Итоги и индексы входят в размер, но не уменьшаются пропорционально движениям. У регистров с тяжёлыми итогами оценка тоже завышена.
- Объекты без даты в сводке идут нулём. Это честный ноль, их вес записан в “не уйдёт”.
- Место освобождается внутри базы, а не на диске. На MS SQL файл данных без сжатия останется прежнего размера, на PostgreSQL место будет свободно внутри таблиц до полной очистки. Что делать с файлом после удаления данных, разобрано в статье о шринке базы на MS SQL.
Отдельно: проверьте объекты со своей очисткой
Разбивка по годам полезна не только для свёртки. Для версий объектов её строят тем же запросом, группируя по реквизиту ДатаВерсии. Если версии лежат на годы дольше настроенного срока хранения, значит, их очистка не работает. По журналу регламентного задания этого не увидеть: оно может годами завершаться без ошибок и ничего не удалять. По годам видно за минуту.
Как это выглядело на двух больших базах
Розничная сеть, 4,2 ТБ. Ожидали увидеть накопленную историю, а 3,85 ТБ оказались служебным кэшем ограничения доступа на уровне записей из БСП, больше всего в нём весила история версий шаблонов ограничения. К дате документов кэш не привязан, и срез по годам не убрал бы из него ни строки. Как разбирали и чем закончилось, описано в кейсе обрезки базы с 4,2 ТБ.
Крупная сеть ломбардов, 2,3 ТБ. Свёртка своей схемой за одно ночное окно увела базу с 2 341 до 573 ГБ, на 75 %: типовая обработка в окно на таком объёме не помещалась. При разборе той же базы 451 ГБ и 113,7 млн строк занимали версии объектов. Задание их очистки годами отрабатывало примерно за две минуты и удаляло ноль строк: срок хранения стоял “бессрочно”, граница удаления выходила 01.01.0001. Подробности в кейсе свёртки базы 2,3 ТБ, а выбор между свёрткой, обрезкой и шринком в статье как уменьшить базу 1С.
В обоих случаях сводка из шага 3 ответила бы на главный вопрос до начала работ.
Если цикл по метаданным идёт слишком долго
На большой базе сводка из шага 3 считается часами, потому что каждый регистр читается целиком. Тот же расчёт без чтения таблиц делает бесплатный калькулятор свёртки: размеры и число записей по годам он берёт из статистики сервера СУБД, сводит их по объектам 1С и считает потенциал при срезе “текущий год и два прошлых”. В отчёт попадают и настройки сервера: резервное копирование, память, параллелизм. Нужны клиент-серверная база на MS SQL Server или PostgreSQL, платформа 8.3.20 и новее и логин СУБД на чтение. Данные базы обработка не меняет, отчёт готов через 15-45 минут.
Если логин СУБД давать не хочется, начните с Карты объёмов: она формирует скрипт для администратора и по результату показывает топ объектов по записям, включая кэши прав и версии. А если сводка показала, что свёртка нужна, и хочется провести её без сюрпризов в остатках, это наша услуга свёртки базы 1С.