Быстрый Поиск Родителя Первого Уровня

Тема в разделе "1C и всё что с ней связано", создана пользователем Tomash, 10 мар 2014.

  1. Tomash

    Tomash Active Member

    Регистрация:
    16 янв 2013
    Сообщения:
    40
    Симпатии:
    0
    здравствуйте

    дорабатываю один отчетик для аналитики, запросом выбирает все продажи, грузит в ТЗ, потом все товары заменяются на группы первого уровня справочника номенклатура, в которых они находятся, уровень вложенности товаров разный, делается это вот так:

    Код ( (Unknown Language)):
            ТзПроданоПерУр=СоздатьОбъект("ТаблицаЗначений");
    ТзПроданоПерУр.Загрузить(ТзПродано);
    ТзПроданоПерУр.ВыбратьСтроки();
    Пока ТзПроданоПерУр.ПолучитьСтроку()=1 Цикл
    Пока ТзПроданоПерУр.Товар.Уровень()>1 Цикл
    ТзПроданоПерУр.Товар=ТзПроданоПерУр.Товар.Родитель;
    КонецЦикла;
    КонецЦикла;
    всё работает нормально, но по замеру в отладчике именно расчет родителя первого уровня для 10-12к товаров занимает 80% времени формирования отчета

    можно ли как-то оптимизировать данный код, или каким-то иным способом ускорить выполнение?
    может быть можно в самом запросе получать родителя первого уровня? сам искал, но находил только получение родителя, а при разной глубине вложения - это не то, что необходимо.
     
  2. Tomash

    Tomash Active Member

    Регистрация:
    16 янв 2013
    Сообщения:
    40
    Симпатии:
    0
    опытным путем установил, что:

    Код ( (Unknown Language)):
                Пока ПустоеЗначение(ТзПроданоПерУр.ТОвар.Родитель)=0 Цикл
    работает в среднем на 30% быстрее, уже неплохо, но может можно что-то ещё выжать?
     
  3. puh14

    puh14 Well-Known Member
    1C Team

    Регистрация:
    11 июл 2008
    Сообщения:
    1.412
    Симпатии:
    0
    Те же яица , но вдруг быстреее
    ПустРод = ПолучитьПустоеЗначение("Справочник.Номенклатура");
    Если Стр.Родитель = пустРод Тогда
     
  4. Glukman

    Glukman Active Member

    Регистрация:
    20 сен 2012
    Сообщения:
    38
    Симпатии:
    0
    ТзПроданоПерУр=СоздатьОбъект("ТаблицаЗначений");
    ТзПроданоПерУр.Загрузить(ТзПродано);
    ТзПроданоПерУр.ВыбратьСтроки();
    Пока ТзПроданоПерУр.ПолучитьСтроку()=1 Цикл
    Спр = ТзПроданоПерУр.Товар;
    ВерхнийРодитель=ЗначениеИзСтрокиВнутр(Шаблон("[ЗначениеВСтрокуВнутр(Спр"+СтрЗаменить(Формат("","С"+(Спр.Уровень()-1))," ",".Родитель")+")]"));
    ТзПроданоПерУр.Товар = ВерхнийРодитель;
    КонецЦикла;

    Попробуйте так.
    Суть убыстрения - будет один проход по циклу без излишнего перебора.
     
  5. vbs

    vbs Well-Known Member

    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    Хороший способ предложил Glukman.
    Но я тоже решил развлечься и проверил свой метод :
    Код ( (Unknown Language)):
    ТзПроданоПерУр=СоздатьОбъект("ТаблицаЗначений");
    ТзПроданоПерУр.Загрузить(ТзПродано);
    ТзПроданоПерУр.ВыбратьСтроки();
    NN = CreateObject("Reference.Номенклатура"); // возможно, название справочника другое
    Пока ТзПроданоПерУр.ПолучитьСтроку()=1 Цикл
    Спр = ТзПроданоПерУр.Товар.;
    Slash = Find(Спр.FullCode(),"/");   
    Code = Left(Спр.FullCode(),Slash-1);
    NN.FindByCode(Code);
    ТзПроданоПерУр.Товар = NN.CurrentItem(); //ВерхнийРодитель;
    КонецЦикла;
    На выборке из 30 тыс. позиций у меня работает в 3 раза быстрее.
    Видимо, преобразование во внутреннее представление и обратно работает все же медленнее
     
  6. Glukman

    Glukman Active Member

    Регистрация:
    20 сен 2012
    Сообщения:
    38
    Симпатии:
    0
    А вот про полный код забыл. Решение не мое, автор если память не изменяет ака Рупор абсурда. на Мисте мелькало.
     
  7. vbs

    vbs Well-Known Member

    Регистрация:
    18 фев 2007
    Сообщения:
    1.708
    Симпатии:
    3
    Решение не мое, автор если память не изменяет ака Рупор абсурда. на Мисте мелькало.

    Я имею обыкновение проверять чужие предложения, если понимаю, как надо :blush:
    Часто интересные идеи мелькают - так я их в свою библиотеку...


    Еще чуточку быстрее должно сработать так :
    Спр = ТзПроданоПерУр.Товар.FullCode();
    Slash = Find(Спр,"/");
    Code = Left(Спр,Slash-1);
     
  8. Tomash

    Tomash Active Member

    Регистрация:
    16 янв 2013
    Сообщения:
    40
    Симпатии:
    0
    спасибо всем, проверил, все варианты рабочие, выдают один и тот же результат, но в данном конкретном отчете скорости на 15к товарах такие:

    1. Оригинал - 90,33 сек
    2. Условие цикла - ПустоеЗначение() - 67,69 сек
    3. Вариант от vbs - 49,15 сек
    4. Вариант от Glukman - 45,74 сек

    не славы ради, но спортивного интереса для ;)
     
Загрузка...

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