Возможно о надоевшем, так как с версиями объектов как только не боролись. Нашел неплохой способ использовать реквизиты, которые в регистре были не задействованы.
В общем, как и многие, в один прекрасный день столкнулся с тем, что регистр сведений "Версии объектов" разросся так сильно, что стал занимать очень много места на SQL. Порядка 4 миллионов записей, половина из которых - дубли. Одно из решений - обработка по удалению одинаковых версий объектов. Решение логичное, но есть одно но - с моей точки зрения, для документов использовать нельзя, так как при перепроведении документа, его движения могут кардинально измениться, из-за изменений настроек программы, учетной политики и т.п. Пройдемся обработкой - даже не узнаем о том, что кто-то что-то перепроводил и не найдем проблему. То есть для данной ситуации важна сама запись в регистре, без данных о версии объекта.
Возникла следующая идея - писать в поле регистра хеш версии объекта, если версии совпадают - хеш одинаковый. Удалять информацию о версии объекта из всех записей с одинаковым хешем, кроме первой. А хеш использовать как ключ поиска. Этим мы решим проблему дублирования и будем видеть все обращения к объектам. Придется переделать отчет истории изменения объектов, чтобы он искал нужную версию объекта по хешу, но это пустяки.
На практике - регистр уже огромный, добавление или изменение его реквизитов приведет к долгой и ненужной реструктуризации. Но оказалось что в регистре уже есть все нужные реквизиты, они просто не используются: УдалитьСжато, Комментарий, ВерсияПроигнорирована.
Решил использовать эти реквизиты для своей задачи: УдалитьСжато - флаг того что запись содержит данные версии (система ставит в истину по умолчанию), Комментарий - строка хеша версии объекта, ВерсияПроигнорирована - запись регистра обработана.
Чтобы не увеличить время записи объектов в системе, обработку регистра вынес в регламентное задание. Регламентное задание разбито на две части - первая проставляет хеши (используется CRC32 как более быстрый) для записей с пустыми хешами. Вторая - чистит версии объектов у записей с одинаковым хешем. Снимает флаг СодержитДанные если версия очищена, и ставит флаг ЗаписьОтработана в любом случае, чтобы не отрабатывать ее в дальнейшем.
Поставил регламентное задание, оно отрабатывало наверно недели две по ночам. Но результат хороший. Делал давно, поэтома сравнивая с данными по проществии года.
Результаты. Было следующее соотношение: количество записей 3,8 млн записей - объем с индексами 14 гигабайт. Сейчас, спустя год 25,3 млн записей, объем с индексами - 31 гигабайт. То есть было примерно 3,5 гигабайта на миллион записей, сейчас - чуть более гигабайта.
Текст процедуры регламентного задания:
Процедура УдалитьДублиВерсийОбъектов() Экспорт
// Используемые поля регистра ВерсииОбъектов:
// Комментарий - хеш версии объекта (ключ для поиска версии)
// ВерсияПроигнорирована - используется наоборот, как флаг того что запись регистра полностью отработана - проставлен хеш, и проверена на дубли
// УдалитьСжато - признак того что запись содержит данные о версии объекта, если Ложь - то данные стерты, и нужны искать запись объекта с таким же хешем и с флагом.
// ищем не проставленные хеши объектов
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 100
| ВерсииОбъектов.Объект
|ПОМЕСТИТЬ ОбъектыБезХеша
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
|ГДЕ
| ВерсииОбъектов.Комментарий = """"
| И ВерсииОбъектов.Объект <> НЕОПРЕДЕЛЕНО
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВерсииОбъектов.Объект,
| ВерсииОбъектов.НомерВерсии
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ОбъектыБезХеша КАК ОбъектыБезХеша
| ПО ВерсииОбъектов.Объект = ОбъектыБезХеша.Объект
|ГДЕ
| ВерсииОбъектов.Комментарий = """"";
// проставляем хеши. CRC32 - самый простой и быстрый.
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Запись = РегистрыСведений.ВерсииОбъектов.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(Запись, Выборка);
Запись.Прочитать();
Если Запись.Выбран() Тогда
ХешМастер = Новый ХешированиеДанных(ХешФункция.CRC32);
ХешМастер.Добавить(Запись.ВерсияОбъекта.Получить());
Запись.Комментарий = Формат(ХешМастер.ХешСумма,"ЧГ=");
КонецЕсли;
Запись.Записать();
КонецЦикла;
КонецЕсли;
// удаляем дубли версий
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 100
| ВерсииОбъектов.Объект
|ПОМЕСТИТЬ НеОбработанныеОбъекты
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
|ГДЕ
| ВерсииОбъектов.ВерсияПроигнорирована = ЛОЖЬ
| И ВерсииОбъектов.Комментарий <> """"
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВерсииОбъектов.Объект,
| ВерсииОбъектов.НомерВерсии,
| ВерсииОбъектов.Комментарий КАК Хеш
|ПОМЕСТИТЬ НеОбработанныеЗаписи
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ НеОбработанныеОбъекты КАК НеОбработанныеОбъекты
| ПО ВерсииОбъектов.Объект = НеОбработанныеОбъекты.Объект
|ГДЕ
| ВерсииОбъектов.ВерсияПроигнорирована = ЛОЖЬ
| И ВерсииОбъектов.Комментарий <> """"
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| НеОбработанныеЗаписи.Объект КАК Объект,
| НеОбработанныеЗаписи.НомерВерсии,
| НеОбработанныеЗаписи.Хеш,
| МИНИМУМ(ЕСТЬNULL(ВерсииОбъектов.НомерВерсии, 0)) КАК НомерВерсииЭталон
|ИЗ
| НеОбработанныеЗаписи КАК НеОбработанныеЗаписи
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
| ПО НеОбработанныеЗаписи.Объект = ВерсииОбъектов.Объект
| И НеОбработанныеЗаписи.Хеш = ВерсииОбъектов.Комментарий
| И НеОбработанныеЗаписи.НомерВерсии > ВерсииОбъектов.НомерВерсии
|
|СГРУППИРОВАТЬ ПО
| НеОбработанныеЗаписи.Объект,
| НеОбработанныеЗаписи.НомерВерсии,
| НеОбработанныеЗаписи.Хеш";
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Запись = РегистрыСведений.ВерсииОбъектов.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(Запись, Выборка);
Запись.Прочитать();
Если Запись.Выбран() Тогда
Если Выборка.НомерВерсииЭталон <> 0 Тогда
Запись.ВерсияОбъекта = Новый ХранилищеЗначения("");
Запись.УдалитьСжато = Ложь;
КонецЕсли;
Запись.ВерсияПроигнорирована = Истина;
КонецЕсли;
Запись.Записать();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Отчет по версиям объектов можете допилить сами, если лень, то в приложении отчет готовый, с возможностью выбора нескольких объектов и с поиском ссылок.
Может кому-то пригодиться.