Книга знаний

1С:Предприятие / Типовые конфигурации

Камешки в стандартной свертке комплексной

Корректная свертка комплексной большого размера с ускорением работы типовой обработкиАвтор статьи: Вик | Редакторы: Волшебник
Последняя редакция №4 от 04.06.06 | История
URL: http://kb.mista.ru/article.php?id=248

Ключевые слова: свертка, комплексная, ускорение


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

Стандартная свертка на серьёзной базе (прядка 2- 3 гигабайт) идет несколько суток. У меня она проходила на тестовой базе от 70 до 94 часов, в зависимости от  загруженности машины параллельными задачами (Р4, 3.0, 1гб оперативки, САТА). Естественно, такое время на живой базе получить нереально – никто на такой срок базы не отдаст, поэтому необходимо ускорять.

Прошу прощения за занудливость, но кому-то это может пригодиться, а кому сильно влом, тот и сам все знает.

Первоначально исходил из Возможно ли ускорить типовую свертку ТиС ?. – цитирую:

 NS
11 - 08.08.04 - 13:57    Раз в 10-ть ускоряется легко....
1) Сдвигается ПО  дату свертки
2) Через ВыгрузитьИтоги() - формируем доки ввода остатков (не проводим, документы в конец дня, предварительно запоминаем последний документ, который надо удалить)
3) Сдвигаем ТА совсем назад.
4) В транзакции по 100 документов - помечаем документы на удаление (по последний, запомненный в предыдущем пункте)
5) Сдвигаем ТА на начало дня свертки
6) Проводим документа ввода остатков
7) Сдвигаем ТА обратно вперед

 NS
12 - 08.08.04 - 15:02    Видимо никому неинтересно...
Можно значительно ускорить и небольшой правкой типовой свертки (не писать свою)

 Gary
13 - 08.08.04 - 15:27    (12) Спасибо ! Именно это я и сделал практически, потому и не смотрел на форум :-)

 Gary
14 - 08.08.04 - 15:29    Взял из обработки с proclub.ru "свертка ИБ" документ "унив.движение по регистру" (как оказалось не все остатки нужны), заполнил его и своей обработкой поичкал документы, правда, по 500 шт, про ТА - упустил, но и так получается вроде

 NS
15 - 08.08.04 - 15:33    (13) Там во первых нужно убрать удаление периодики,
Запрос переписать под выгрузитьИтоги...
Убрать провети в момент ввода остатков
Удаление делать в транзакции по 100, и с предварительным сдвигом ТА назад.
Потом сдвинуть ТА вперед, перепровести доки ввода остатков, и еще раз Та вперед.
В принципе за час - переписывается легко, и остается весь их бред с контролями.


Именно так я и сделал – изменил стандарную по этому принципу: сдвинул ТА на дату свертки, передвинул (руками) БИ на последний квартал сворачиваемого периода, отказался от «их бреда с контролями», обошел удаление периодики и вставил транзакции при удалении документов.

После устранения мелких камешков (счет КМС имеет 2 одинаковых субконто, но по нему нет проводок). Процесс прошел за 7-8 часов. Но проверка результатов удручила. НДС поплыл на 2-3 миллиона за квартал. Иными словами «их бред» был не полным бредом.

Сделал подробные печати с указанием выполняемого этапа и с выводом даты и времени сообщения. Выяснил, что после возврата всех проверок на место, но сохранив транзакции и сдвижку ТА и БИ получил общее время работы 26 часов, причем 18-20 часов идет на контроль допустимости удаления пар накладная-счет/фактура. Дополнительно к этому, нельзя отказываться от удаления периодики. Дело в том, что некоторые периодические реквизиты, которые существенно используются при проведении документов, устанавливаются удаляемыми документами. При удалении этих документов естественно удаляется и история периодических реквизитов.

Попутно еще раз убедился в сильной чувствительности результатов свертки к чистоте исходной базы – в ней не должно быть нераспределенных партий или непроводимых при восстановлении ГП документов.
Полученное время – 26 часов заметно лучше 70-90 часов, но также неудовлетворительно – требуется подготовительно- заключительное время, включающее выгрузку-загрузку базы до и после свертки, контроль корректности результатов в сравнении с исходной базой. А такое сравнение можно более ли менее достоверно провести только после восстановления ГП на свернутой базе.

Выход найден в том, чтобы на выходных подготовить базу восстановлением ГП.

После этого подготовленная база грузится на место и в копию, которая предоставляется бухгалтерам в качестве уже готовой базы прошлого года. А в рабочей базе жестко закрывается прошлый год от всякого вмешательства и она отдается для работы в течение недели. Еще одна копия подготовленной базы используется для свертки в течение рабочей недели так, чтобы результаты самых трудоемких процессов были сохранены на диске. При этом есть время и для контроля результатов этой, в данном случае пробной свертки, что нелишне. А затем на следующих выходных опять снимается рабочая база и на ней запускается тот же процесс свертки, но в варианте использования сохраненных на диске результатов, что позволяет ускорить процесс еще примерно в 3-4 раза.

В окончательном виде порядок действий был таков:

1. Восстанавливаем ГП от начала жизни.
2. Удаляем из плана счетов счет КМС и после этого выполняем удаление помеченных объектов  (обязательно!).
3. Удаляем из справочника ФизЛиц периодический реквизит «СтатусНеРезидента» (еще один камешек потом можно вернуть, все равно иностранцев в моей базе нет)
4. Устанавливаем БИ руками на последний квартал сворачиваемого периода в меню Операции/УправлениеБИ
5. Модифицируем стандартную свертку следующим образом:

А) для управления ТА:

    //Изменение ТА
    РабочаяДата(обДатаСвертки);     
    СтараяТА=ПолучитьДатуТА();
    УстановитьТАпо(обДатаСвертки);     
    // 
    
    Если фрмВыполнитьСверткуОиБУ = 1 Тогда
        обВыполнитьСверткуОиБУ();
    КонецЕсли;

    // Восстановление ТА
        УстановитьТАпо(СтараяТА);
 
 
Б) для включения механизма транзакций меняем процедуру удаления документов:

Процедура оуУдалениеДокументов(СворачиваемыеДокументы)
    
    Перем Док;
    
    Док = СоздатьОбъект("Документ");
    
    СчетчикДокументов = 0;
    СчетчикУдаленныхДокументов = 0;

    пфДобавитьСообщение(" ");

    //Сдвигаем ТА назад и Начинаем транзакцию
        УстановитьТАпо(Дата(1980,1,1));     
    НачатьТранзакцию();    
    //КонецВставки             

    СворачиваемыеДокументы.ВыбратьСтроки();
    Пока СворачиваемыеДокументы.ПолучитьСтроку() = 1 Цикл
        Если СворачиваемыеДокументы.Документ.Выбран()=1 Тогда

            Если Док.НайтиДокумент(СворачиваемыеДокументы.Документ) <> 1 Тогда
                Продолжить;
            КонецЕсли;

            Если Док.Проведен()=1 Тогда               
                Док.СделатьНеПроведенным();           
            КонецЕсли;                               

            Если СворачиваемыеДокументы.Операция = 1 Тогда

                // удаляем документ из ИБ
                Док.Удалить(0);

                СчетчикУдаленныхДокументов = СчетчикУдаленныхДокументов + 1;

            ИначеЕсли СворачиваемыеДокументы.Операция = 2 Тогда

                // удаляем только табличную часть документа не удаляя его самого т.к. на него есть ссылки в объектах
                // и эти ссылки могут понадобится для операций с ИБ после даты свертки

                Если (Док.КоличествоСтрок() > 0) Тогда 
                    Док.УдалитьСтроки();
                КонецЕсли;

                Если ГлЕстьРеквизитШапки("ФлагСвертки",Док.Вид())=1  Тогда
                    Док.ФлагСвертки = 1;                
                КонецЕсли;
                Док.Комментарий = "Свернут обработкой Свертка ИБ " + ТекущаяДата();
                Док.Записать();

                СчетчикДокументов = СчетчикДокументов + 1;

            КонецЕсли;         
            
//Вставляем фиксацию транзакции через 100 документов и начинаем новую, информационное сообщение
            ккк=СчетчикУдаленныхДокументов+СчетчикДокументов;                                            
Если ккк % 100 = 0 Тогда                                                         
                пфОбновитьСообщение("Обработано "+Док.ДатаДок+"  "+ккк);                        
                ЗафиксироватьТранзакцию();                                                                   
НачатьТранзакцию();                                                         
            КонецЕсли;        
//Конец вставки                                                               

            //пфОбновитьСообщение("Документов свернуто: "+Формат(СчетчикДокументов,"Ч5")
//+", документов удалено: "+Формат(СчетчикУдаленныхДокументов,"Ч5"));

        КонецЕсли;
    КонецЦикла;  

    //Окончательно фиксируем транзакцию после всех удалений
ЗафиксироватьТранзакцию();       


КонецПроцедуры  // оуУдалениеДокументов(СворачиваемыеДокументы)


В) В процедуреобСверткаОУ вносим изменение, для того, чтобы самый длительный процесс – контроль допустимости удаления пар накладная –счет/фактура сохранить на диске (здесь оператор
оуПодготовкаСпискаСсылок(СсылкиНаДокументы);

взят в условный оператор, который на первом этапе сохраняет результаты на диск, а на втором этапе вместо расчета считывает результаты с диска):

        Если СтандартнаяСвертка=1 Тогда
            
            оуПодготовкаСпискаСсылок(СсылкиНаДокументы);              
            
            СписокПараметров=СоздатьОбъект("СписокЗначений");
            Текст=СоздатьОбъект("Текст");
        
            Ном=0;
            СсылкиНаДокументы.ВыбратьСтроки();
            Пока СсылкиНаДокументы.ПолучитьСтроку()=1 Цикл
                Ном=Ном+1;
                        СписокПараметров.УдалитьВсе(); 
                СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(СсылкиНаДокументы.ДокументИБ));
                СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(СсылкиНаДокументы.ОбъектИБ));
                СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(СсылкиНаДокументы.Атрибут));
                Стр=СписокПараметров.ВСтрокуСРазделителями();
                Текст.ДобавитьСтроку(Стр);
            КонецЦикла;
            Текст.Записать("S:\свертка\СсылкиНаДокументы.txt");
            Сообщить("    - Выгрузка СсылкиНаДокументы ЗАВЕРШЕНА !!! выгружено "+Ном+" строк");   
        Иначе
            СписокПараметров=СоздатьОбъект("СписокЗначений");
            Текст=СоздатьОбъект("Текст");
            Текст.Открыть("S:\свертка\СсылкиНаДокументы.txt");
        
            Для Ном=1 по Текст.КоличествоСтрок() Цикл
                Стр=Текст.ПолучитьСтроку(Ном);
                        Если СтрДлина(Стр) = 0 Тогда
                             Продолжить;
                        КонецЕсли;
                        СписокПараметров.УдалитьВсе(); 
                       СписокПараметров.ИзСтрокиСРазделителями(Стр);
                                                            
                СсылкиНаДокументы.НоваяСтрока();
                СсылкиНаДокументы.ДокументИБ=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(1));
                СсылкиНаДокументы.ОбъектИБ=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(2));
                СсылкиНаДокументы.Атрибут=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(3));
            КонецЦикла;
            Сообщить("    - Загрузка СсылкиНаДокументы ЗАВЕРШЕНА !!! загружено "+Ном+" строк");   
        КонецЕсли;   


Г) выполняем такую модифицированную свертку – примерно 26 часов. Восстанавливаем в ней ГП и контролируем совпадение с исходной несвернутой по регистрам и состоянию бухгалтерского учета.

После этого на выходные снимаем работающую базу и запускаем ту же свертку в режиме использования сохраненных на диске результатов. Время 6-7 часов. После этого на свернутой базе восстанавливаем ГП и проверяем результаты, сравнивая с исходной несвернутой базой.

Заключительный этап теперь со всеми подготовительно-заключительными этапами, восстановлением ГП и контролями укладывается в 1,5 суток, что уже вполне приемлемо в реальной жизни.

Дополнительно к указанным изменениям в процедурах выдачи сообщений делаем изменения для лучшего контроля хода работы:
    //Состояние(Сообщение);
    Сообщить(""+ТекущееВремя()+" - "+ТекущаяДата()+" - "+Сообщение);


Д) Кроме указанного напоролся на потерю некоторых периодических реквизитов в справочникеОС – стандартная сверка здесь некорректна. Пришлось выгрузить-загрузить эту периодику своей обработкой, которая написана на основе соответствующих фрагментов стандартной свертки:

Процедура обДобавитьЗначениеВИБ(Д, Кол, Элемент, Значение, Тип,Длина,Точность)

    П = СоздатьОбъект("Периодический");
    П.ИспользоватьОбъект(Кол, Элемент);
    П.ДатаЗнач = Д;

    Если Тип <> "" Тогда
        П.НазначитьТип(Тип,Длина,Точность);
    КонецЕсли;

    П.Значение = Значение;
    П.Записать();

КонецПроцедуры // обДобавитьЗначениеВИБ


// Сохраняет переодические реквизиты, чтобы записать их после удаления 
// документов, которые более не нужны
//
Процедура обЗапомнитьПериодическиеЗеквизиты(Идентификатор)
    
    СписокПараметров=СоздатьОбъект("СписокЗначений");
    Текст=СоздатьОбъект("Текст");
    КоличествоСтрок=Текст.КоличествоСтрок();        
    Если КоличествоСтрок>0 Тогда
        Для От=1 По КоличествоСтрок Цикл
            Текст.УдалитьСтроку(От);
        КонецЦикла;
    КонецЕсли;     
    Ном=0;  
    обДатаСвертки=Дата(2005,12,31);

    Справ=СоздатьОбъект("Справочник."+Идентификатор);
    МетаСправочник=Метаданные.Справочник(Справ.Вид());
    Справ.ВыбратьЭлементы(0);
    П = СоздатьОбъект("Периодический");
    Пока  Справ.ПолучитьЭлемент() =1 Цикл 
        Элемент=Справ.ТекущийЭлемент();
        Для А=1 По МетаСправочник.Реквизит() Цикл
            Реквизит = МетаСправочник.Реквизит(А);
            Если Реквизит.Периодический = 0 Тогда
                Продолжить;
            КонецЕсли;
            Если Реквизит.ИзменяетсяДокументами = 0 Тогда
                Продолжить; 
            КонецЕсли;    
            Если (Элемент.ЭтоГруппа()=1) и (Реквизит.Использование="ДляЭлемента") Тогда
                Продолжить;
            КонецЕсли;
            Если (Элемент.ЭтоГруппа()=0) и (Реквизит.Использование="ДляГруппы") Тогда
                Продолжить;
            КонецЕсли;
            П.ИспользоватьОбъект(Реквизит.Идентификатор, Элемент);
            П.ОбратныйПорядок();
            П.ВыбратьЗначения(); 
            ДатаЗ=ПолучитьПустоеЗначение(); 
            Значение=ПолучитьПустоеЗначение(); 
            Документ=ПолучитьПустоеЗначение(); 
            Пока П.ПолучитьЗначение() = 1 Цикл 
                ДатаЗ=П.ДатаЗнач;
                Значение=П.Значение; 
                Документ=П.ТекущийДокумент(); 
                Если ДатаЗ<=обДатаСвертки Тогда
                    Прервать;
                КонецЕсли;
            КонецЦикла;
            Если ПустоеЗначение(Документ)=1 Тогда
                Продолжить;
            КонецЕсли; 
            Тип=Реквизит.Тип; 
            Длина=Реквизит.Длина;
            Точность=Реквизит.Точность;
            Если (ТипЗначенияСтр(Значение) = "Справочник") или (ТипЗначенияСтр(Значение)="Перечисление")  Тогда
                Тип = ТипЗначенияСтр(Значение)+"."+ Значение.Вид();   
            КонецЕсли; 
            
            //обДобавитьЗначениеВИБ(обДатаСвертки, Реквизит.Идентификатор,Элемент, Значение, Тип,Длина,Точность)
            Ном=Ном+1;
                    СписокПараметров.УдалитьВсе(); 
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(обДатаСвертки));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Реквизит.Идентификатор));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Элемент));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Значение));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Тип));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Длина));
            СписокПараметров.ДобавитьЗначение(ЗначениеВСтрокуВнутр(Точность));
            Стр=СписокПараметров.ВСтрокуСРазделителями();
            Текст.ДобавитьСтроку(Стр);
        КонецЦикла;
    КонецЦикла;
    Текст.Записать("S:\Nofelet\свертка\ПериодикаОС.txt");
    Сообщить("    - Выгрузка ПериодикаОС ЗАВЕРШЕНА !!! выгружено "+Ном+" строк");   
КонецПроцедуры // обЗапомнитьПериодическиеЗеквизиты
//*******************************************
Процедура Сформировать()
    обЗапомнитьПериодическиеЗеквизиты("ОсновныеСредства");
КонецПроцедуры
//*******************************************
Процедура Загрузить()
            СписокПараметров=СоздатьОбъект("СписокЗначений");
            Текст=СоздатьОбъект("Текст");
            Текст.Открыть("S:\Nofelet\свертка\ПериодикаОС.txt");
        
            Если Текст.КоличествоСтрок()=0 Тогда
                Предупреждение("Файл пустой!");
                //Возврат;
            КонецЕсли;     
            
            Для Ном=1 по Текст.КоличествоСтрок() Цикл
                Стр=Текст.ПолучитьСтроку(Ном);
                        Если СтрДлина(Стр) = 0 Тогда
                             Продолжить;
                        КонецЕсли;
                        СписокПараметров.УдалитьВсе(); 
                        СписокПараметров.ИзСтрокиСРазделителями(Стр);
                                                            
                обДатаСвертки=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(1));
                РеквизитИдентификатор=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(2));
                Элемент=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(3));
                Значение=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(4));
                Тип=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(5));
                Длина=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(6));
                Точность=ЗначениеИзСтрокиВнутр(СписокПараметров.ПолучитьЗначение(7));
                
                Если Найти(Тип,"Перечисление")>0 Тогда
                    Перечисл=Перечисление.ПолучитьАтрибут(СтрЗаменить(Тип,"Перечисление.",""));
                    Для н=1 По Перечисл.КоличествоЗначений() Цикл
                        Если ""+Значение=""+Перечисл.ЗначениеПоНомеру(н) Тогда
                            Значение=Перечисл.ЗначениеПоНомеру(н);
                            Прервать;
                        КонецЕсли;
                    КонецЦикла;
                КонецЕсли;
                //УстановитьРеквизитСправочника(Элемент, РеквизитИдентификатор, Значение, обДатаСвертки, Тип);      
                обДобавитьЗначениеВИБ(обДатаСвертки, РеквизитИдентификатор,Элемент, Значение, Тип,Длина,Точность);    

                Сообщить(""+Элемент+" - "+Значение+" - "+РеквизитИдентификатор+" - "+Тип+" - "+Длина+" - "+Точность);
            КонецЦикла;
            Сообщить("    - Загрузка СсылкиНаДокументы ЗАВЕРШЕНА !!! загружено "+Ном+" строк");   
КонецПроцедуры
//****************************************************************


После окончания всех работ вернуть на место «СтатусНеРезидента» и КМС.
Ну вот, пожалуй и все.
Надеюсь, кому нибудь это поможет.

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика