Книга знаний

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

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

Корректная свертка комплексной большого размера с ускорением работы типовой обработкиАвтор статьи: Вик | Редакторы:
Последняя редакция №2 от 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

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