7.7 Оптимизация времени выполнения

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 7.7"", создана пользователем nvartfox, 5 авг 2010.

  1. TopicStarter Overlay
    nvartfox
    Offline

    nvartfox

    Регистрация:
    1 апр 2009
    Сообщения:
    36
    Симпатии:
    0
    Баллы:
    1
    Здравствуйте,всем ! Упала на сопровождение нестандартная конфигурация по учету основных средств. Возникла следующая проблема,есть процедура расчета амортизации основных средств, размер базы данных 25000 записей, при запуске на моем рабочем месте считает за 2 минуты, расчет на рабочем месте растягивается на 6 часов.
    Отличие рабочих месте
    мое : база в формамате DBF, 1 Гб ОЗУ база на самом компьютере релиз платформы 27
    рабочая станция заказчика база формате MS SQL Server подключение через удаленный рабочий стол, программа запускается на сервере, ОЗУ сервеа 2 Гб, платформа 1с 27
    Процедура расчета амортизации приведена ниже
    Код:
    Процедура ОбработкаПроведения()
    Перем Запрос, ТекстЗапроса;              
    сообщить("Процесс стартовал :"+ТекущееВремя());
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    //Создание объекта типа Запрос
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = 
    "//{{ЗАПРОС(Сформировать)
    |Период с ДатаДок по ДатаДок;
    |Без итогов;
    |ОС = Справочник.ОсновныеСредства.ТекущийЭлемент;
    |БС = Справочник.ОсновныеСредства.БалансСтоимость;
    |Состояние = Справочник.ОсновныеСредства.Состояние;
    |Срок = Справочник.ОсновныеСредства.СрокПолезногоИспользования;
    |Способ = Справочник.ОсновныеСредства.СпособНачисленияАмортизации;
    |Группировка ОС без групп;
    |Группировка БС;
    |Группировка Состояние;
    |Группировка Срок;
    |Группировка Способ;
    |Условие(БС > 0);
    |Условие((ПустоеЗначение(Состояние)=0) и (Состояние<>Перечисление.ТипОперации.Выбыло));
    |Условие(Срок > 0);
    |Условие(Способ = 3);
    |"//}}ЗАПРОС
    ;
    // Если ошибка в запросе, то выход из процедуры
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
    КонецЕсли;
    Запрос.Выгрузить(ТЗ);   
    сообщить("Таблица данных сформирована :"+ТекущееВремя()); 
    
    СчетчикСтрок = 0;
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл  
    СчетчикСтрок = СчетчикСтрок+1;
    КонецЦикла;	
    сообщить("Отобрано для расчета "+СчетчикСтрок+" строк");
    
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл          
    сообщить("Обрабатывается "+ТЗ.ОС+" "+ТекущееВремя());
    СведенияОбОС = глРасчетАмортизацииОС(ТЗ.ОС, ДатаДок);
    Остаток = ТЗ.БС - СведенияОбОС.Получить("Износ");
    СуммаИзноса = Окр(ТЗ.БС/ТЗ.Срок,2);
    Если Остаток <=0 Тогда
    Продолжить;
    КонецЕсли;
    
    Операция.НоваяПроводка();
    Операция.Кредит.Счет = СчетПоКоду("02.1");
    Операция.Кредит.ОсновныеСредства = ТЗ.ОС;
    Операция.Сумма = Мин(Остаток,СуммаИзноса);
    Операция.Содержание = "Начисленна амортизация";
    сообщить("Проводка сформирована "+ТЗ.ОС+" "+ТекущееВремя());
    КонецЦикла;
    Операция.Записать();
    
    
    Процедура глРасчетАмортизацииОС из глобального модуля конфигурации
    Код:
    Функция глРасчетАмортизацииОС(ОС, ДатаРасчета) Экспорт
    Перем СведенияОбОС;
    
    СведенияОбОС = СоздатьОбъект("СписокЗначений");
    
    СведенияОбОС.Установить("Контрагент", ОС.Контрагент.Получить(ДатаРасчета));
    СведенияОбОС.Установить("Основание", ОС.Основание.Получить(ДатаРасчета));
    //	СведенияОбОС.Установить("БС", ОС.БалансСтоимость.Получить(ДатаРасчета));
    СведенияОбОС.Установить("Состояние", ОС.Состояние.Получить(ДатаРасчета));
    СведенияОбОС.Установить("КонтрагентОт", ОС.КонтрагентОт.Получить(ДатаРасчета));
    СведенияОбОС.Установить("ОснованиеОт", ОС.ОснованиеОт.Получить(ДатаРасчета));
    СведенияОбОС.Установить("Источник", ОС.Источник.Получить(ДатаРасчета));
    Если КонМесяца(РабочаяДата()) > КонецРассчитанногоПериодаБИ() Тогда
    Стр = "На " + Формат(РабочаяДата(), "Д (0)ДДММГГГ") + " бухгалтерские итоги не рассчитаны!"+РазделительСтрок+
    "Расчет итогов выполняется в режиме"+РазделительСтрок+
    """Операции - Управление бухгалтерскими итогами"".";
    Иначе     
    //БухИт.ПериодМ(ДатаРасчета);
    //СведенияОбОС.Установить("Износ", БухИт.СКК("02.1",,, ОС));
    
    БухИт = СоздатьОбъект("БухгалтерскиеИтоги");
    БухИт.ИспользоватьСубконто(ВидыСубконто.ОсновныеСредства,ОС);
    БухИт.ВыполнитьЗапрос(ДатаРасчета,ДатаРасчета,"01.1",,,,,"СК");
    БухИт.ВыбратьСубконто(ВидыСубконто.ОсновныеСредства,ОС);
    Пока БухИт.ПолучитьСубконто(ВидыСубконто.ОсновныеСредства,ОС) = 1 Цикл
    //	 Если БухИт.Субконто(ВидыСубконто.ОсновныеСредства) = ОС Тогда
    СведенияОбОС.Установить("БС",БухИт.СКД("С"));
    СведенияОбОС.Установить("Кол",БухИт.СКД("К"));
    //				Прервать;
    //		КонецЕсли;		
    КонецЦикла;
    
    БухИт = СоздатьОбъект("БухгалтерскиеИтоги");
    БухИт.ИспользоватьСубконто(ВидыСубконто.ОсновныеСредства,ОС);
    БухИт.ВыполнитьЗапрос(ДатаРасчета,ДатаРасчета,"02.1");
    БухИт.ВыбратьСубконто(ВидыСубконто.ОсновныеСредства);
    Пока БухИт.ПолучитьСубконто(ВидыСубконто.ОсновныеСредства) = 1 Цикл
    Если БухИт.Субконто(ВидыСубконто.ОсновныеСредства) = ОС Тогда
    СведенияОбОС.Установить("Износ",БухИт.СКК());
    Прервать;
    КонецЕсли;		
    КонецЦикла;
    
    КонецЕсли;
    
    Возврат СведенияОбОС;
    
    КонецФункции //глРасчетАмортизацииОС()
    
    
    Массив формируемый запросом по времени формируется примерно одинаково, тормозит расчет амортизации Главная загадка почему разница во времени выполнения разы ? Является ли причиной код процедуры,если да то как его можно оптимизировать ? Если нет что можно сделать по железу
  2. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Все логично. Запос в цикле - ЖЕСТЬ. Это не профессионально. Тем более что в данном случае не используются возможности SQL (прямые запросы). Конечно же файловый вариант сработает БЫСТРЕЕ. Вынесте запрос к БИ из цикла. Формируте ОБЩИЙ а потом пользуйтесь выборками - все наладится
  3. TopicStarter Overlay
    nvartfox
    Offline

    nvartfox

    Регистрация:
    1 апр 2009
    Сообщения:
    36
    Симпатии:
    0
    Баллы:
    1
    Можно немного уточнить ответ в части выноса запроса к БИ из цикла. Подозреваю что не хватает опыта, поэтому если возможно по подробнее, я вижу на данный только один цикл в котором вызываются запросы к БИ, это цикл в процедуре ОбработкаПроведения() в котором обрабатывается массив данных по основным средствам
  4. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Внутри глРасчетАмортизацииОС
    Код:
    БухИт.ВыполнитьЗапрос(ДатаРасчета,ДатаРасчета,"01.1",,,,,"СК");
    
    
    Я бы сделал так:
    В обработке процедения посде запроса:
    1) Значения запроса выгружаетм в СписокЗначений (понадобится в качестве фильтра)
    2) Делаем запрос к БИ (используя в качестве фильтра список из запроса) - это наше самое "узкое" место. Но поскольку делается 1 раз все будет ОК
    3) В цикле форрирем проводки используя формулу из глРасчетАмортизацииОС
  5. TopicStarter Overlay
    nvartfox
    Offline

    nvartfox

    Регистрация:
    1 апр 2009
    Сообщения:
    36
    Симпатии:
    0
    Баллы:
    1
    Спасибо за помощь, получилось немного по другому, для данного конкретного случая объединили и скорректировали процедуру, в результате получили код, исполняется 25 секунд на том же объеме данных
    Код:
    Процедура ОбработкаПроведения()
    Перем Запрос, ТекстЗапроса;              
    сообщить("Процесс стартовал :"+ТекущееВремя());
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    //Создание объекта типа Запрос
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = 
    "//{{ЗАПРОС(Сформировать)
    |Период с ДатаДок по ДатаДок;
    |Без итогов;
    |ОС = Справочник.ОсновныеСредства.ТекущийЭлемент;
    |БС = Справочник.ОсновныеСредства.БалансСтоимость;
    |Состояние = Справочник.ОсновныеСредства.Состояние;
    |Срок = Справочник.ОсновныеСредства.СрокПолезногоИспользования;
    |Способ = Справочник.ОсновныеСредства.СпособНачисленияАмортизации;
    |Группировка ОС без групп;
    |Группировка БС;
    |Группировка Состояние;
    |Группировка Срок;
    |Группировка Способ;
    |Условие(БС > 0);
    |Условие((ПустоеЗначение(Состояние)=0) и (Состояние<>Перечисление.ТипОперации.Выбыло));
    |Условие(Срок > 0);
    |Условие(Способ = 3);
    |"//}}ЗАПРОС
    ;
    // Если ошибка в запросе, то выход из процедуры
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
    КонецЕсли;
    Запрос.Выгрузить(ТЗ);   
    сообщить("Таблица данных сформирована :"+ТекущееВремя()); 
    
    СчетчикСтрок = 0;
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл  
    СчетчикСтрок = СчетчикСтрок+1;
    КонецЦикла;	
    сообщить("Отобрано для расчета "+СчетчикСтрок+" строк");
    БухИт = СоздатьОбъект("БухгалтерскиеИтоги");
    БухИт.ИспользоватьСубконто(ВидыСубконто.ОсновныеСредства);
    //   сообщить(ДатаДок);
    БухИт.ВыполнитьЗапрос(ДатаДок,ДатаДок,"02.1");  
    БухИт.ВыбратьСубконто(ВидыСубконто.ОсновныеСредства);
    Пока БухИт.ПолучитьСубконто(ВидыСубконто.ОсновныеСредства) = 1 Цикл 
    Строк = 0;
    ТЗ.НайтиЗначение(БухИт.Субконто(ВидыСубконто.ОсновныеСредства),Строк,"ОС");   
    Если Строк = 0 тогда Продолжить; КонецЕсли;
    
    Аморт = БухИт.СКК();
    Остаток = ТЗ.ПолучитьЗначение(Строк,"БС") - Аморт;
    СуммаИзноса = Окр(ТЗ.ПолучитьЗначение(Строк,"БС")/ТЗ.ПолучитьЗначение(Строк,"Срок"),2);
    Если Остаток <=0 Тогда
    Продолжить;
    КонецЕсли;
    
    Операция.НоваяПроводка();
    Операция.Кредит.Счет = СчетПоКоду("02.1");
    Операция.Кредит.ОсновныеСредства = ТЗ.ПолучитьЗначение(Строк,"ОС");
    Операция.Сумма = Мин(Остаток,СуммаИзноса);
    Операция.Содержание = "Начисленна амортизация";
    КонецЦикла;         
    сообщить("Проводки сформированы"+" "+ТекущееВремя());
    Операция.Записать();
    КонецПроцедуры  
    
    
    
  6. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.520
    Симпатии:
    407
    Баллы:
    104
    Сделали тоже в принципе тоже самое что я вам предлагал. Главное было - убрать запрос из цикла.

    Но можно еще оптимизировать. Например:
    Код:
    сообщить("Отобрано для расчета "+ТЗ.КоличествоСтрок()+" строк");
    
    

Поделиться этой страницей