Очистка таблиц итогов регистров остатков от лишних записей в 1с   

Как известно, для регистров остатков хранит отдельно движения по регистру и отдельно итоги по регистру на начало периодов (зависит от периодичности оперативных итогов). Так вот, идеальное состояние этих 1с регистров возникает в момент загрузки данных из архива. В этот момент в таблице итогов регистра отсутствуют «нулевые записи». «Нулевые записи» – это значит, что в регистре итогов присутствует запись, в которой каждый из ресурсов регистра – нулевой.

Фактически, нормально обходится без такой записи. Скорее наоборот, ей приходится эти записи фильтровать. Как же они появляются? А появляются они в момент проведения документа по составу измерений, по которому документ делает движения. Такие «нулевые записи» характеры для 1с регистров, в которых сильно меняется набор измерений – т.е. часть измерений является реквизитом типа «Документ». Хорошим примером является регистр партий. По нему в течение периода итогов (скажем месяц) пришло несколько десятков партий товара, при этом на конец периода осталась, как правило, одна или несколько партий (обычный вариант списания по FIFO). Но по мере работы базы, изо дня в день в некоторый момент времени каждая из партий имелась в наличии, и при этом оставила след в таблице итогов регистра на данный период. Так, как данное сочетание измерений к концу периода закончилось, (партия была распродана), то в таблице итогов по данному сочетанию измерений остались одни нули.

Это мы берем пример работы в последнем по времени периоде итогов. А если перепровести документ годичной давности? Тогда во всех последующих периодах, начиная с текущего, по каждому из наборов измерений присутствующих в движениях данного документа в таблице итогов будут присутствовать данные наборы измерений. И если партия закончилась сразу же, то, значит, все они будут нулевыми. Если в приходной накладной 100 строк, то с учетом годичной давности мы получим 1200 лишних записей в таблице итогов регистра.

Также очень хорошо это можно понять на примере таблицы итогов регистра резервов. Тут вообще ситуация такая, что количество «нулевых» записей по итогам регистра будет стремиться к 100% от общего количества записей в таблице итогов. Так как резервы создаются на короткое время (ну скажем от трех дней до недели), то, как правило, большинство из них не переходят на следующий месяц, а снимаются либо накладными, либо снятиями резерва. По идее в таблице итогов должны присутствовать только резервы, переходящие через период итогов (в общем случае на следующий месяц). Но, как уже было сказано выше, это совсем не так.

Я произвел замеры на своей базе по регистру «Заказы». В этом регистре учитываются заказы товара поставщику, которые снимаются приходом товара или отменяются. В общем, и целом – полная аналогия с регистром резервов. Так вот – из порядка 900000 записей в таблице итогов из них пустыми были порядка 880000, то есть полезный объем (20000) составлял от полного объема около 2,5%. Остальные данные были излишними…

Разумеется, я не мог с этим смириться просто так. Вскоре была написана обработка, которая выдает соотношение полезной информации в таблицах итогов по всем присутствующим в конфигурации регистрам остатков и полного объема таблиц. Кроме того, можно сразу удалить эти неиспользуемые записи.

Обработка работает только для баз в формате SQL. Написана с использованием Rainbow. Если у вас нет компоненты Rainbow, то ее можно загрузить здесь. Используйте обработку на свой страх и риск.

Текст обработки представлен ниже:

Перем ТекМета;
Процедура Чистить()
    СтрокаСообщения="Удаление записей из таблицы итогов - необратимый процесс!
    |Отменить данную операцию после выполнения будет невозможно!
    |Вы уверены, что хотите продолжить?";
    Если Вопрос(СтрокаСообщения,4)=6 Тогда
        ЗапросРадуги=СоздатьОбъект("ODBCQuery");
        Для к=1 по Метаданные.Регистр() Цикл
            Если Метаданные.Регистр(к).ТипРегистра="Остатки" Тогда
                ТекИдентификатор=Метаданные.Регистр(к).Идентификатор;
                ТекСиноним=Метаданные.Регистр(к).Синоним;
                Если ТекСиноним="" Тогда
                    ТекСиноним=ТекИдентификатор;
                КонецЕсли;
                ИмяТаблицы=ТекМета.ИмяТаблицыИтогов(ТекИдентификатор);
                ТекстЗапроса="DELETE
                |FROM "+ИмяТаблицы+"
                |WHERE ";
                Для й=1 по Метаданные.Регистр(к).Ресурс() Цикл
                    ТекИдРесурса=Метаданные.Регистр(к).Ресурс(й).Идентификатор;
                    ТекстЗапроса=ТекстЗапроса+?(й=1,""," AND ")+"(SP"+ТекМета.ИдРесурсаРегистра(ТекИдентификатор,ТекИдРесурса)+"=0)";
                КонецЦикла;
                //Теперь выполняем запрос
                Если ЗапросРадуги.Prepare(ТекстЗапроса,1,1)=1 Тогда
                    Если ЗапросРадуги.Open()=1 Тогда
                        Сообщить("Обработан регистр <"+ТекСиноним+">","i");
                        ЗапросРадуги.Close();
                    Иначе
                        Предупреждение("Ошибка открытия запроса!",10);
                    КонецЕсли;
                    ЗапросРадуги.Reset();
                Иначе
                    Предупреждение("Ошибка выполнения запроса!",10);
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        ЗапросРадуги="";
    КонецЕсли;
КонецПроцедуры
//________________________________________________________
Процедура Посчитать()
    ЗапросРадуги=СоздатьОбъект("ODBCQuery");
    Для к=1 по Метаданные.Регистр() Цикл
        Если Метаданные.Регистр(к).ТипРегистра="Остатки" Тогда
            ТекИдентификатор=Метаданные.Регистр(к).Идентификатор;
            ТекСиноним=Метаданные.Регистр(к).Синоним;
            Если ТекСиноним="" Тогда
                ТекСиноним=ТекИдентификатор;
            КонецЕсли;
            ИмяТаблицы=ТекМета.ИмяТаблицыИтогов(ТекИдентификатор);
            ТекстЗапроса="SELECT COUNT(*)
            |FROM "+ИмяТаблицы+"
            |WHERE ";
            Для й=1 по Метаданные.Регистр(к).Ресурс() Цикл
                ТекИдРесурса=Метаданные.Регистр(к).Ресурс(й).Идентификатор;
                ТекстЗапроса=ТекстЗапроса+?(й=1,""," AND ")+"(SP"+ТекМета.ИдРесурсаРегистра(ТекИдентификатор,ТекИдРесурса)+"=0)";
            КонецЦикла;
            //Выполняем запрос на общее количество
            ПолноеЧисло=0;
            Если ЗапросРадуги.Prepare("SELECT COUNT(*) FROM "+ИмяТаблицы,1,1)=1 Тогда
                Если ЗапросРадуги.Open()=1 Тогда
                    ЗапросРадуги.GotoNext();
                    Если ЗапросРадуги.IsOK()=1 Тогда
                        ПолноеЧисло=ЗапросРадуги.GetLong(0);
                    КонецЕсли;
                    ЗапросРадуги.Close();
                Иначе
                    Предупреждение("Ошибка открытия запроса!",10);
                КонецЕсли;
                ЗапросРадуги.Reset();
            Иначе
                Предупреждение("Ошибка выполнения запроса!",10);
            КонецЕсли;
            //Теперь выполняем запрос на количество пустых
            ПустоеЧисло=0;
            Если ЗапросРадуги.Prepare(ТекстЗапроса,1,1)=1 Тогда
                Если ЗапросРадуги.Open()=1 Тогда
                    ЗапросРадуги.GotoNext();
                    Если ЗапросРадуги.IsOK()=1 Тогда
                        ПустоеЧисло=ЗапросРадуги.GetLong(0);
                    КонецЕсли;
                    ЗапросРадуги.Close();
                Иначе
                    Предупреждение("Ошибка открытия запроса!",10);
                КонецЕсли;
                ЗапросРадуги.Reset();
            Иначе
                Предупреждение("Ошибка выполнения запроса!",10);
            КонецЕсли;
            Сообщить("Пустых строк итогов по регистру <"+ТекСиноним+"> : "+ПустоеЧисло+" из "+ ПолноеЧисло+" возможных.","i");
        КонецЕсли;
    КонецЦикла;
    ЗапросРадуги="";
КонецПроцедуры
//________________________________________________________
Процедура ПриОткрытии()
    Попытка
        ЗагрузитьВнешнююКомпоненту("rainbow.dll");
        ТекМета=СоздатьОбъект("MetaDataWork");
    Исключение
        Форма.кнПосчитать.Доступность(0);
        Форма.кнЧистить.Доступность(0);
    КонецПопытки;
КонецПроцедуры

Эту обработку можно загрузить в разделе "Скачать".

 

 

Перепечатка, воспроизведение в любой форме, распространение, в том числе в переводе, любых материалов с сайта www.softpoint.ru возможны только с письменного разрешения компании "СофтПоинт". Это правило действует для всех без исключения случаев, кроме тех, когда в материале прямо указано разрешение на копирование (основание: Закон Российской Федерации "Об авторском праве и смежных правах").