Ускоряем списание партий УПП 1.2 / 1.3 / УТ 10.3

Не секрет, что многие пользователи, использующие партионный учет (а таких очень много, даже среди огромных холдингов, несмотря на пропаганду РАУЗ) при больших нагрузках сталкиваются с резким замедлением списания партий.  

Чего только не придумывалось, чтобы как то решить эту проблему – это и отсроченное списание партий ночью и сверхчастое обновление статистики SQL, но почему-то среди общих рекомендаций не встречается оптимизация именно типового кода УПП.

 

В типовой УПП механизм списания партий реализован очень давно. Его основная логика не менялась как минимум с релиза 1.2.16 по 1.3.26, т.е 4 года. Скорее всего за эти годы не раз сменялись внутренние стандарты разработки прикладных решений в самой 1с. На текущий момент не рекомендуется использовать в запросе соединение с подзапросом, но так как код был достаточно старый, то такое соединение использовалось до релиза 1.3.26. Ситуация наконец была исправлена в релизе  1.3.27, но как показала личная практика это решение не принесло значимой пользы при больших нагрузках.

 

Задолго до релиза 1.3.27 я столкнулся с тем, что на предприятии имеющем розничное подразделение с несколькими сотнями документов «Отчет о розничных продажах» в день со средним количеством строк порядка 100 уже невозможно было провести весь объем документов даже за окно доступное ночью (работа базы была почти круглосуточная, но ночью нагрузка значительно меньше). В среднем документ «Отчет о розничных продажах» проводился по 3-5 минут, если кто-то вдруг решил перепровести документ днем, то время проведения могло доходить до 30 минут, что конечно сильно тормозило других пользователей. Т.е. ситуация стала абсолютно невыносимой. Доступа к серверу SQL в той организации я не имел, поэтому у меня был один выход – попробовать оптимизировать типовой код.

 

Для поиска узкого места выгрузил копию базы в файловую (на тот момент она еще выгружалась, достаточно было очистить регистр сведений «Версии объектов»). Отладчиком был найден типовой код на котором висело по минуте – это были банальные строки Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам) в процедурах ПолучитьДеревоПартийНаСкладахУпр, ПолучитьДеревоПартийНаСкладахБух, ПолучитьДеревоПартийНаСкладахНал общего модуля УправлениеЗапасамиПартионныйУчет.

 

Посмотрев текст запроса и грубо упростив его получаем:

 

ВЫБРАТЬ

ПартииТоваровНаСкладах.Номенклатура

ИЗ

РегистрСведений.СписанныеТовары КАК СписанныеТовары

ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах.Остатки(

&Дата,

Номенклатура В

(ВЫБРАТЬ

РегистрСведений.СписанныеТовары.Номенклатура

ИЗ

РегистрСведений.СписанныеТовары

ГДЕ

РегистрСведений.СписанныеТовары.Регистратор = &Ссылка)) КАК ПартииТоваровНаСкладах

ПО СписанныеТовары.Номенклатура = ПартииТоваровНаСкладах.Номенклатура

ГДЕ

СписанныеТовары.Регистратор = &Ссылка

 

 

Что мне здесь не понравилось:

1) Из регистра сведений «Списанные товары» информация выбирается не один раз, а несколько

2) Получается что сначала идет соединение, а только потом отбор условием ГДЕ СписанныеТовары.Регистратор = &Ссылка.

 

Обе эти проблемы решаются элементарно – перед

Возврат Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

В трех вышеуказнных функция вставляем код

   Запрос.Текст =
   
«ВЫБРАТЬ
    |    *
    |ПОМЕСТИТЬ СписанныеТовары
    |ИЗ
    |    РегистрСведений.СписанныеТовары
    |ГДЕ
    |    Регистратор В (&ОсновнойДокумент, &Ссылка)
    |ИНДЕКСИРОВАТЬ ПО Номенклатура;
    |
    |»
+ СтрЗаменить(Запрос.Текст, «РегистрСведений.СписанныеТовары», «СписанныеТовары»);

Этот сверхпростой код принес колоссальный эффект – документы которые проводились по 3-5 мин стали проводиться по 20-40 секунд. Пробовал добавлять различные индексы кроме Номенклатуры и играться с условиями – где-то это давало дополнительный прирост местами даже в 2 раза.

 

Этот код ускоряет весь механизм списания партий. На других документах списывающих партии время проведения так же значительно снизилось.

 

Так же я пробовал эту модификацию на текущем месте работы – здесь не было особых проблем с проведением документов списывающих партии, тем не менее, код дал ускорение при восстановлении партионной последовательности при закрытии месяца. Особенно это было заметно в случае когда сервер 1с длительное время работал без перезагрузки. При переходе на релиз 1.3.27 раз уж был изменен типовой код в этом месте решил отказаться от своей доработки, но на следующий же день получил несколько звонков от сбыта, что реализации стали проводиться заметно дольше. Сейчас уже более полугода работаем на более мощном сервере, но повторять эксперимент уже нет желания.

 

Позже на просторах интернета был найден и другой способ – сверхчастое обновление статистики только по нужным регистрам.

 

Дополнено 25.06.2013 — Теперь исправление запроса корректно и для ордерной схемы. Код раскрашен разукрашкой — //infostart.ru/public/19856/

98 Comments

  1. Антон Ширяев

    Если вам так же небезразлична скорость работы типовых конфигураций, просьба поддержать мой вопрос к Борису Нуралиеву №293 — http://forum.infostart.ru/forum24/topic88121/message931662/#message931662

    Конечно вряд ли он будет отвечать на технические вопросы, но может быть хотя бы полученные вопросы будут переданы разработчикам для ознакомления.

    Reply
  2. Aletar

    Ага, знакомая тема, я у нас также сделал. С год назад я здесь на форуме задавал вопрос про эту оптимизацию — почему такую очевидную оптимизацию кода не сделают сами в 1С, кто-то сказал, что скорее всего этот запрос ещё с тех времен, когда не поддерживались пакетные запросы. Конечно ситуация все равно удручает. Вопрос к Нуралиеву поддержу.

    Reply
  3. kapustinag

    Нашли это место и исправили точно так же в нашей УПП (нашел не я) примерно год назад, получили тоже очень серьезное ускорение. Кроме ускорения, есть и еще эффект — так как медленное проведение блокировало некоторые действия других пользователей, то еще и количество и время блокировок снизились.

    Я после этого написал в техподдержку (по-моему, на адрес v8@1c.ru), изложил в письме этот способ ускорения партионных запросов, но никакого нормального ответа не получил. И изменений в типовом коде тоже никаких не последовало.

    Кстати, там есть еще один момент — если используется ордерная схема, то партии списываются не обязательно документом-регистратором. Они могут списываться расходными ордерами, связанными с данным документом. Это тоже можно учесть в запросе, особых проблем нет.

    Reply
  4. Антон Ширяев

    (3) kapustinag,

    Как раз примерно год назад в мае 2012 на мисте в одной из тем про взаимоблокировке я предложил это попробовать.

    Я не претендуя на то, что я был первооткрывателем, но тем не менее сам подобного готового решения до моего поста на мисте встречал.

    если используется ордерная схема, то партии списываются не обязательно документом-регистратором. Они могут списываться расходными ордерами, связанными с данным документом

    Да, для ордерной схемы немного по-другому, я не использую ордерную схему для случая списания партий, поэтому не заострил на этом внимания.

    В посте (6) исправленный вариант.

    Reply
  5. Re:аниматор

    Добавил этот код в УТ 10.3. Действительно быстрота проведения документов очевидная, НО только для документов РТУ (с текущего склада).

    По ордерной схеме (Расходный ордер на товары) партии после такой доработки НЕ списываются! пришлось откатить изменения, но идея интересная

    P.S. для полноты статьи не плохо бы отразить для ордерной схемы.

    Reply
  6. Антон Ширяев

    (5) Re:аниматор,

    Проверил для ордерной схемы в УПП, думаю в УТ 10 то же самое — нужно из РС «Списанный товары» отбирать не только &ОсновнойДокумент, но и &Ссылка.

    Запрос выглядит так:

    Запрос.Текст =

    «ВЫБРАТЬ

    | *

    |ПОМЕСТИТЬ СписанныеТовары

    |ИЗ

    | РегистрСведений.СписанныеТовары

    |ГДЕ

    | Регистратор В (&ОсновнойДокумент, &Ссылка)

    |ИНДЕКСИРОВАТЬ ПО Номенклатура;

    |

    |» + СтрЗаменить(Запрос.Текст, «РегистрСведений.СписанныеТовары», «СписанныеТовары»);

    Прошу проверить тех кто использует ордерную схему. Если все в порядке, включу в статью + добавлю что работает не только в УПП, но и в УТ.

    Reply
  7. Vladimir_Konyrev

    Добрый день.

    Так все же, поможет ли описанный вами способ ускорить работу в последних релизах УПП (1.3.40)? Есть смысл вносить изменения в свою конфу?

    Reply
  8. Антон Ширяев

    (7) Vladimir_Konyrev,

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

    Попробуйте на копии своей базы восстановить партионную последовательность с доработкой и без.

    Если сервер достаточно мощный и статистика регулярно обновляется, то проблема зачастую и не проявляется.

    От доработки хуже тоже не станет. Очень бы хотелось чтоб типовые УПП 1.3 и УТ 10 были доработаны самой фирмой 1С. Прошу поддержать вопрос Нуралиеву.

    Reply
  9. Re:аниматор

    (6) Работает, Спасибо!

    P.S. делал на УТ 10.3

    Reply
  10. Vladimir_Konyrev

    (8)

    В момент проведения самой РТиУ проблем больших нет, есть проблема долгого восстановления последовательности.

    Вопрос не поддержу, не ввиду того, что считаю его не важным, а ввиду того, что БГ на него отвечать не будет ввиду того, что он Стратег, а не исполнитель.

    Reply
  11. tiniji

    1С знает об этой проблеме с 2008-2009 года. Судите сами, как они исправляют ошибки.

    Кстати есть куча других ошибок, которые видимо так и останутся в УТ 10.3 навсегда )))

    Reply
  12. ZLENKO

    Зачем исправлять старые ошибки когда есть куча новых 🙂

    Reply
  13. fsv_kanash

    (9) Не нашел в УТ 10.3 процедур ПолучитьДеревоПартийНаСкладахБух, ПолучитьДеревоПартийНаСкладахНал

    Процедуру ПолучитьДеревоПартийНаСкладахУпр нашел, код перед

    Возврат Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

    добавил. После проведения РТУ -по регистру ПартииТоваровНаСкладах (упр) пропали все движения,после удаления кода и перепровделения документа, движения так и не появились ))(

    Reply
  14. Антон Ширяев

    (13) fsv_kanash,

    Не нашел в УТ 10.3 процедур ПолучитьДеревоПартийНаСкладахБух, ПолучитьДеревоПартийНаСкладахНал

    Процедуру ПолучитьДеревоПартийНаСкладахУпр нашел

    Да, для УТ 10.3 требуется вносить дополнение только в процедуру ПолучитьДеревоПартийНаСкладахУпр. Статья писалась в первую очередь про УПП, про УТ добавлял позже и не учел этот момент.

    После проведения РТУ -по регистру ПартииТоваровНаСкладах (упр) пропали все движения,после удаления кода и перепровделения документа, движения так и не появились ))(

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

    Reply
  15. ZLENKO

    Уберите еще отборы виртуальной таблицы ПартииТоваровНаСкладах.Остатки (ограничение будет идти по соединению таблиц) в виде: Номенклатура В (ВЫБРАТЬ РегистрСведений.СписанныеТовары.Номенклатура ИЗ РегистрСведений.СписанныеТовары ГДЕ РегистрСведений.СписанныеТовары.Регистратор = &Ссылка)

    получите еще хороший бонус по ускорению! (по крайней мере на MS SQL Server) 🙂

    P.S.: За такое на экзамене на специалиста ставили 2 балла, но факты вещь упрямая — без отборов намного быстрее!

    А вот индексирование временной таблицы даст прирост только на докуметах с несколькими сотнями строк, а при небольшом количестве строк только замедляет создание временной таблицы.

    Reply
  16. Re:аниматор

    (14) в УТ нет отложенного списания партий. Хотя в своей конфе УТ я это сделал по принципу УПП, но после перехода на MS SQL 2008 64 бит эта потребность отпала и отключил.

    Reply
  17. Amara

    У нас такая же ситуация, но все руки не доходили в виду загруженности большими проектами. Спасибо! Воспользуюсь вашим вариантом.

    Reply
  18. internetname

    Чем быстрее, тем лучше.

    Reply
  19. candy_sk

    а чем этот отчет отличается от стандартного в УПП ?

    Reply
  20. Антон Ширяев

    (19) candy_sk,

    а чем этот отчет отличается от стандартного в УПП ?

    По каким признакам было принято решение, что это ОТЧЕТ?

    Это доработка типового кода УПП 1.2 / УПП 1.3 / УТ 10.3, которая решает проблему долгого проведения документов, которые списывают партии — Реализация, Перемещение, Отчет о розничных продажах и др.

    Reply
  21. powerpc

    Протестировал на тестовой базе :

    // без исправления:

    // файловая:

    // Время выполения: t=376 сек.(6,26666667 мин.)

    // Время выполения: t=351 сек.(5,85000000 мин.)

    // когда нет работающих пользователей

    // Время выполения: t=240 сек.(4,00000000 мин.)

    // SQL

    // Время выполения: t=509 сек.(8,48333333 мин.)

    // когда нет работающих пользователей

    // Время выполения: t=464 сек.(7,73333333 мин.)

    ***********************************************************

    // с исправлением:

    // файловая

    // Время выполения: t=345 сек.(5,75000000 мин.)

    // Время выполения: t=265 сек.(4,41666667 мин.)

    // SQL

    // когда нет работающих пользователей

    // Время выполения: t=618 сек.(10,30000000 мин.)

    Reply
  22. powerpc
    Reply
  23. Антон Ширяев

    (21) powerpc,

    Если бы не было реального прироста в моем конкретном случае, этой публикации здесь бы не было.

    Ситуации бывают разные в вашем случае пока виден обратный эффект.

    Вы не уточнили сколько раз проводились измерения. На каком документе проходило тестирование. Сколько в среднем строк в исследуемом типе документов. В некоторых случаях строка «ИНДЕКСИРОВАТЬ ПО Номенклатура» может дать замедление.

    Если есть возможность, повторите эксперимент 3-5 раз, обращая внимание та то, большой ли разбег результатов, т.к. существует вероятность, что замедление после исправления обусловлено другими факторами.

    Reply
  24. Антон Ширяев

    (22) powerpc,

    Правил только —

    Общий модуль: УправлениеЗапасамиПартионныйУчет

    : Функция ПолучитьДеревоПартийНаСкладахУпр (МоментКон, СтруктураПараметров)

    в УТ 10.3 в упор не вижу таких же процедур с окончаниями «Нал» и «Бух».

    Как я уже писал выше, я работая только с УПП, поэтому и статья в первую очередь была про УПП.

    В УТ 10.3 есть только ПолучитьДеревоПартийНаСкладахУпр, поэтому исправляем только ее.

    Если у вас эта процедура и так выполняется в пределах 10 секунд, то и особого прироста скорее всего ждать не стоит, т.к. некоторое время уходит на создание временной таблицы и ее индексирование.

    Reply
  25. powerpc

    (23)

    >> Если бы не было реального прироста в моем конкретном случае, этой публикации здесь бы не было.

    Согласен. Поэтом и себе хочу взять на вооружение.

    >> Ситуации бывают разные в вашем случае пока виден обратный эффект.

    Если бы эффект был обратный обратному, то и моего поста возможно здесь не было, либо был бы, с благодарностью или плюсом.

    >>> Вы не уточнили сколько раз проводились измерения.

    5 без исправления, 3 раза с исправлениями. С исправлениями в монопольном режиме, когда не было никого кроме меня в базе.

    >>> На каком документе проходило тестирование. Сколько в среднем строк в исследуемом типе документов.

    Документ: «Перемещение товаров». 2600 документов. Кол-во строк в документах от 1 до сотни.

    Reply
  26. powerpc

    (24)

    >> Если у вас эта процедура и так выполняется в пределах 10 секунд, то и особого прироста скорее всего ждать не стоит, т.к. некоторое время уходит на создание временной таблицы и ее индексирование.

    // Время выполения: t=618 сек.(10,30000000 мин.)

    10 минут vs 7 минут

    P.S. Тема очень интересная, т.к. имеющееся железо уже разогнали, осталась логика приложения ))))

    Reply
  27. Антон Ширяев

    (25) powerpc,

    5 без исправления, 3 раза с исправлениями. С исправлениями в монопольном режиме, когда не было никого кроме меня в базе.

    Ваше тестирование было по сути по одному разу для каждых различных условий. При возможности повторите по нескольку раз для одних и тех же условий.

    Документ: «Перемещение товаров». 2600 документов. Кол-во строк в документах от 1 до сотни.

    Попробуйте провести один и тот же документ со 100 строками раз 10 подряд. Будет ли время проведения стабильно? В моем случае время первого проведения было больше времени последующих в большинстве случаев.

    Соответственно попробовать провести тот же документ в той же базе раз 10 после доработки. Так же повторить тест с без использования индекса по номенклатуре.

    Reply
  28. Антон Ширяев

    (26) powerpc,

    Перечитал ваши посты еще раз.

    Получается что 2600 документов проводятся 7-10 минут. Это значит один документ в среднем проводится четверть секунды. Думаю для такого варианта оптимизации никакой не требуется.

    Мне оптимизация требовалась когда 1 документ проводился по 3-5-7 минут, а у вас 2600 документов за это время проводится.

    Reply
  29. powerpc

    (27) хорошо, попробую, спасибо.

    Хотя не думаю, что ускорение хорошо получать за два и несколько последовательных проведений одного и того же документа. А то придётся вывешивать рядом с кнопкой «ОК» ещё и «ОК-ОК» (Double-OK) 🙂 Думаю последовательное проведение проходит быстрее из за кэширования последних запросов в оперативной памяти. Прирост виден и на моих первых двух тестах без исправления — 25 секунд (почти полминуты).

    Ещё очень странно то, что по логике Вашего исправления действительно должен произойти значительный прирост, а его нет. Может версия SQL Server 2008 R2 уже оптимизирует как-то такие «неправильные» запросы ?

    Reply
  30. Антон Ширяев

    (29) powerpc,

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

    Reply
  31. powerpc

    (30) мы тоже сначала сервер купили. Теперь на хорошем геймерском компе проводим ))))))))

    Reply
  32. ZLENKO

    (22) powerpc, Я писал выше о том что для получения ускорения нужно убрать отборы виртуальной таблицы остатков партий, которые имеют вид запросов. Гарантированно получите ускорение 🙂

    Reply
  33. ZLENKO

    (31) powerpc, на геймерском компе с оверклокерской памятью наверняка быстрее будет, чем на серверной оперативке 🙂

    Reply
  34. powerpc
    Reply
  35. ZLENKO

    (34) powerpc, этот и по складам тоже:

    Номенклатура В

    (ВЫБРАТЬ

    РегистрСведений.СписанныеТовары.Номенклатура

    ИЗ

    РегистрСведений.СписанныеТовары

    ГДЕ

    РегистрСведений.СписанныеТовары.Регистратор = &Ссылка)

    И (Склад В

    (ВЫБРАТЬ

    РегистрСведений.СписанныеТовары.Склад

    ИЗ

    РегистрСведений.СписанныеТовары

    ГДЕ

    РегистрСведений.СписанныеТовары.Регистратор = &Ссылка) ИЛИ Склад = &ПустойСклад)

    Reply
  36. ZLENKO

    (34) powerpc, я пробовал еще предварительно получать отдельным запросом списки номенклатуры и складов и потом указывать их параметром вот так: Номенклатура В (&СписокНоменклатура) И Склад В (&СписокСклад), но существенной разницы с тем что их вообще не указывать не заметил. Ограничение по номенклатуре и складу выполняется по соединению.

    Reply
  37. powerpc

    (35) ZLENKO.PRO, здорово. А косяков не будет при списании партий, из других складов или из другой номенклатуры не спишутся ? Вы проверяли ?

    Reply
  38. powerpc

    (36) ZLENKO.PRO, во, убрал как вы посоветовали:

    // Время выполнения: t=1 991 сек.(33,18333333 мин.)

    обратное ускорение пошло…. всю номенклатуру шерстит по ходу… и все склады иже с ними.

    Reply
  39. ZLENKO

    (37) powerpc, а какие косяки могут быть ? Номенклатура и склады обрубаются через «ВНУТРЕННЕЕ СОЕДИНЕНИЕ».

    Пользуюсь уже несколько лет на нескольких больших базах.

    Reply
  40. ZLENKO

    (38) powerpc, У вас база на какой СУБД ?

    Reply
  41. powerpc

    (40) ZLENKO.PRO, в т.ч. и на файловой, дальше пробовать не буду, результат отруба отбора очевиден ….

    Reply
  42. ZLENKO

    (41) powerpc, на файловой вполне вероятно что будет хуже. Просто на файловой у меня и проблемы такой не было 🙂 А вот на базах по 50-80 Гб на MS SQL однозначно сильно помогает.

    Reply
  43. ZLENKO

    Для файловой оптимальнее, наверное, будет сначала получить записи из списанных товаров и из них сформировать параметры отбора Номенклатура В (&СписокНоменклатура) И Склад В (&СписокСклад) для второго основного запроса. Результат первого запроса добавить через менеджер временных таблиц во второй.

    Reply
  44. ZLENKO

    Кстати автор предлагает получать все поля:

    Запрос.Текст =

    «ВЫБРАТЬ

    | *

    |ПОМЕСТИТЬ СписанныеТовары

    |ИЗ

    | РегистрСведений.СписанныеТовары

    а полей там немало, а реально нужно получить только небольшую часть.

    Лучше перечислить что именно нужно получить…

    Reply
  45. powerpc

    (44) ZLENKO.PRO, неа, не отыскать грааль. Запрос 1с-чный оптимален, имхо. Думаю ЦУП-ом прошлись по ключевому запросу

    Reply
  46. ZLENKO

    (45) powerpc, спорить не буду — разница при выборке скорее всего будет незначительна при реальных объемах выборки в несколько десятков или сотен строк. На тысячах строк вполне вероятно уже будет ощущаться зависимость от объема выбираемых данных. А вот при помещении всего этого во временную таблицу — ежу понятно что разница будет большая создавать таблицу из 5 полей или из 50 полей(именно столько в регистре Списанные Товары)!

    Reply
  47. ZLENKO

    А по поводу неоптимальной работы запроса по партиям разработчики из 1С давно признали проблему, но рекомендуют лечить ее более частым обновлением статистики MS SQL Server. Просто из-за этих вложенных запросов в отборе виртуальной таблицы планировщик запросов MS SQL Server с ума сходит 🙂 Но даже при актуальной статистике у меня примерно двукратный прирост скорости при убирании этих отборов. А ведь при перепроведении по партиям статистика быстро устаревает из-за изменения в регистре… Так что думайте сами, решайте сами…

    На файловой скорее всего просто убрать нельзя — надо менять на параметры в отборе, а под MS SQL специально недавно проверял надо просто убрать отборы. Движок MS SQL эффективено работает с соединениями таблиц и отбор номенклатуры и складов происходит через них.

    Reply
  48. ZLENKO

    Я на самом деле много возился с этим запросом в базе УПП пару лет назад — пробовал и так и эдак с целью ускорения проведения по партиям в целом. Однако я тогда уперся в медленную запись регистров партий 🙁 а в УПП их 3 регистра (упр, бух, нал)…

    Reply
  49. ZLENKO
    Reply
  50. Антон Ширяев

    (31) powerpc,

    Геймерский комп конечно хорошо, но в подавляющем большинстве случаев в крупных компаниях работают на серверах без разгона процессора и памяти, а они для серверов обычно имеют более низкие штатные частоты, особенно для не сверхдорогих серверов. Да еще и дисковая подсистема зачастую собрана в RAID5 ради экономии.

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

    То что я описал в статье как раз помогло мне выбраться из такой ситуации.

    Reply
  51. powerpc

    (50) arteast, а сюда можно этот ответ скопировать, а то у меня доступа нет к сожалению к партнерскому форуму.

    Reply
  52. Антон Ширяев

    (44) ZLENKO.PRO,

    Кстати автор предлагает получать все поля:

    а полей там немало, а реально нужно получить только небольшую часть.

    Лучше перечислить что именно нужно получить…

    Лучше всегда понятие относительное. В моем случае задача была минимально исправить конфигурацию для беспроблемного ее обновления и при этом получить увеличение производительности.

    Доработка как раз сделана таким образом, что скорее всего будет работать даже после доработки этого места 1С. Это подтвердилось когда вышел релиз 1.3.27 УПП, где 1С вынесла вложенный запрос получения остатков партий в подзапрос. Возможно вы получали прирост от убирания отборов именно пока это был вложенный запрос.

    Reply
  53. powerpc

    (51) я и не спорю, наверно в УПП это хорошо работает, тут пишут, что там сразу в три регистра бух, нал, упр движения формируются, может в этом фишка исправленного запроса проявляется. Геймерский комп как раз более доступен, чем даже недорогой сервер с RAID (я полным бэкапам больше доверяю, сорри). Просто я проверяю возможность вашим способом ускорить проведение партий и на УТ 10.3.

    Reply
  54. ZLENKO

    (50) arteast, если посмотриш внимательнее, то увидиш что это я написал ответ, а не мне 🙂

    Reply
  55. ZLENKO

    (52) powerpc, это мой ответ «Индексирование во временных таблицах делать не стоит — выигрыша по скорости не получите из-за небольшого объема выборки, а замедление при создании временных таблиц из-за индексирования будет весьма ощутимым (проверено на практике).» Дело в том что автор запроса предлагал делать индексирование во временных таблицах. В тексте запроса который я привел выше индексирование я убрал при копипасте оттуда.

    Reply
  56. ZLENKO

    (53) как раз от выноса в подзапрос мало что меняется. Не буду навязывать свою точку зрения по данному вопросу. Запрос, который я считаю оптимальным приведен в (49). Хотя пожалуй стоит убрать вложенность запроса в основном запросе — смысла в ней нет. А вообще конечно надо пробовать в каждой конкретной ситуации разные варианты. Например у меня отбор по номенклатуре и складу через параметры немного лучше работал на документах до 100 строк, а на документах более 100 строк уже быстрее работал отбор по номенклатуре и складу через временные таблицы (как сделано в (49)), причем чем больше документ тем это значительнее проявлялось. На документах в несколько строк при актуальной статистике и рассчитанных на нужный момент итогах разницы по сравнению с типовым запросом может и не быть 🙂

    Reply
  57. Re:аниматор

    УТ 10.3

    Произвел манипуляции с запросом, вроде документы стали быстрее проводится (хотя и без этого кода не тормозило), думал ускорится обработка «Проведение по партиям» и сегодня!

    запустил обработку «Проведение по партиям» скорость упала в раза 4.5:-(, то что раньше делалось часа 2, делается порядка 8.5 часов

    Удалил этот код, сработало за 2 часа. Оптимизация для УТ 10.3 под сомнением ….

    Reply
  58. powerpc

    (58) Re:аниматор, точно. Скорее во время экспериментов с запросом злобный админ сменил на сервере SATA на SSD вот и взлетело у автора.

    Reply
  59. Re:аниматор

    (59) Раньше был сервер 32 бита, стала падать программа и висеть проведение доков окала минуты две, перевели на MS SQL 2008 64 бита, скорость проведения увеличилась в раз 20. БД 130 гигов. окала 200 пользователей. Вот это я понимаю оптимизация. По началу вставил код, вроде казалось что по быстрее, хотя народ и не жаловался и ранее после перевода на 64 бита. Но вчера запустив обработку … лег спать под утро, не выспался не фига сидел ждал окончание… злой сегодня =)

    Reply
  60. Антон Ширяев

    (58) Re:аниматор, (59) powerpc,

    Я никого не принуждаю использовать эту доработку, хотя использую сам. Если у вас и так быстро работает не трогайте это место.

    Теперь я понимаю почему 1С не трогает тут ничего. Ситуация неоднозначная. Эффективность когда и так все работает быстро может быть обратной.

    Но тем кто столкнется с реальной проблемой думаю будет полезно знать куда можно посмотреть.

    Reply
  61. Re:аниматор

    (61) Это понятно, каждый выбирает свой путь, без претензий. Может данный код и полезен для проведения одного документа интерактивно, но групповым методом тут трындец полный =) Тормоза идут снежным комом, т.е. 5 дней проводятся час, следующие 5 дней, 1.5 часа, далее 5 дней 2 часа и т.д.

    Сидел материлллл …. себя конечно, что не проверил в тестовой БД перед тем как делать в рабочей

    Лично я не рекомендую этот код внедрять для УТ 10.3. т.к. восстановление партий за месяц важнее чем проведение одного интерактивно документа. В моем случае

    Reply
  62. ZLENKO

    (60) Re:аниматор, а у вас статистика апдейтится на MS SQL ?

    sp_updatestats выполняете как часто на базе ?

    Reply
  63. ZLENKO

    (62) Re:аниматор, судя по симптомам у вас быстро устаревает статистика — настройте задание.

    У меня например каждые 15 минут выполняется:

    USE [workbase]

    GO

    EXEC SP_UPDATESTATS;

    GO

    DBCC FREEPROCCACHE;

    GO

    Все счастливы 🙂

    Reply
  64. Re:аниматор

    (64) Спасибо, проверю каждые 15 минут! У нас каждую ночь идет обслуживание БД, обновление статистики и т.д. делается часов 8 обслуживание

    Статистика обновляется каждую ночь 1 раз, проверил логи в обслуживание 2 часа тратится на выполнение этого задания, не будет ли завалом при каждые 15 минут?

    Reply
  65. arteast

    Что самое забавное, без этого изменения перепроводка документа ОРП занимала 5-40 минут в зависимости от объёма строк (розничная торговля косметикой и бытхимом) ЧТо касается восстановления партий за месяц — суток не хватало. Сейчас же за сутки партии восстанавливаются за 8-10 месяцев. При чём возрастания времени как у (62) не наблюдается.

    Для меня — это однозначно показатель)

    Конфа УТ 10.3, платформа 8.1, сервак на SSD с секционированием данных по годам (каждый год на отдельном SSD)

    Reply
  66. arteast

    (56) ZLENKO.PRO, пробовал без индексирование, время проведения документов увеличилось. Как проведение документа в 10 строк, так и дока в 3к строк.

    В ближайшее время переведу клиента на 8.2 — проверим, в платформе ли дело) Пока заказчик доволен и месяц тестирования ничего не «вылезло».

    Именно потому, твой ответ «Лучше так не делать, я пробовал у меня не получилось» (по смыслу именно так) для меня абсолютно не аргументирован)

    Reply
  67. Re:аниматор

    (66) MS SQL 32 или 64 бит? Версия?

    Reply
  68. arteast

    (68) Re:аниматор, 64 -bit это винда. Насчёт дистрибутива скуля не в курсе.

    После перестроения индексов минут 3-10 минут, но уже на след день опять более получаса проводится ОРП(

    До внедрения этого кода.

    Reply
  69. ZLENKO

    (67) Аргументы требуются для доказательства чего либо. В данном случае никаких доказательств не требуется 🙂

    Вы видимо плохо понимаете суть и смысл индексирования. Проверьте лучше в регистре ПартииТоваровНаСкладах у вас измерения Склад и Номенклатура индексированные ? И весьма желательно чтобы порядок измерений был именно такой «Склад, Номенклатура» и потом остальные измерения. Тогда есть вероятность использования части составного индекса по регистру. Индексировать временную таблицу в данном случае бессмысленно. ИМХО

    Reply
  70. adhocprog

    Спасибо! Ценная статья!

    Reply
  71. Shrek2015

    спасибо! полезно очень!

    Reply
  72. Fominro

    И от меня спасибо за статью, помогло.

    Reply
  73. jefjef

    У нас серьезная проблема с проведением по партиям, в списанных товарах около 300 тыс. записей за 5 лет работы, за последний год уже около 70 тыс.

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

    Стандарное УПП.

    35% времени обработки занимает выполнение запроса в ПолучитьДеревоПартийНаСкладахБух

    Занялся проблемой оптимизации кода, наткнулся на эту тему.

    После рекомендованного в этой теме создания временной таблицы СписанныеТовары — выполнение запроса стало занимать 45% времени обработки. Это навело на мысль что создание временной таблицы и дальнейшее ее юзанье в запросе не есть гуд.

    Проверил эту мыслю — выкинул из запроса временные таблицы СписанныеТовары и стандартную уппшную ПартииТоваровНаСкладах, а также убрал нафиг из параметров ПартииТоваровНаСкладахБухгалтерскийУчет.Остатки( запросики по условию на номенклатуру и склад из списанных товаров, в них нет понту — все равно со списанными товарами идет внутреннее соединение.

    В результате этих манипуляций получаю один запрос ВЫБРАТЬ на две таблицы с внутренним соединением между собой.

    После запуска проведения по партиям запрос отнимает всего 20% времени выполнения и на первое место по нагрузке выходит ДвиженияРегистра.Записать(Истина); Проведение проводится за час и главбух танцует от радости.

    Со временем записи движений уже спорить сложно, что есть то есть. Быстрее не будет.

    Так вот какой я для себя сделал вывод: чем запрос проще, тем он быстрее. Чем меньше в нем конструкций ВЫБРАТЬ, тем меньше манипуляций делает SOL сервер. Не надо решать за SQL как и в какой последовательности ему работать, нужно просто запросить что нужно.

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

    Reply
  74. Gilev.Vyacheslav

    (74) jefjef, готовы Вам помочь переписать код на более эффективное использование ваших аппаратных ресурсов, вот пример нашего опыта http://www.gilev.ru/teremok/

    Reply
  75. jefjef

    (75) Gilev.Vyacheslav, спасибо за предложение, в примере Вашего опыта не написано ничего, кроме благодарности за троекратное ускорение проведения по партиям, а троекратного ускорения я добился и без посторонней помощи, причем делюсь здесь своим опытом бесплатно, а не за 80 тыс. руб.

    Reply
  76. vis_tmp

    У меня на УТ 10.3 подтвердилсь — ускорение есть и существенное.

    Спасибо автору!

    Reply
  77. vis_tmp

    +(77)База файловая, за 2,5 года, объёмом в 15 Гб

    Reply
  78. Gilev.Vyacheslav

    (75) Gilev.Vyacheslav, ускорим МИНИМИУМ в 3 раза (а может и больше), после того как вы ускорить больше не сможете

    за бесплатные советы ни кто ответственности не несет, а мы подписываем договор и гарантируем результат

    если эта статья не обеспечит желаемого результата, обращайтесь

    Reply
  79. AlexO

    (79) Gilev.Vyacheslav,

    Статья обеспечивает наглядный результат, так как тут исправлен явный косяк 1С в типовой УПП, коих море разливанное. Автор оптимизировал то, что было на поверхности и само просилось исправиться — сделал запрос через ВТ, что для слабых серверов — самое то.

    И получил отличный результат.

    Для мощных машие это, может, и не актуально — но там затыки в других местах.

    В том числе, наверняка и в подобных этому.

    Reply
  80. belovo3000

    Огромный респект! Без этого когда обработка проведения по партиям занимала около 9 часов сейчас все провелось за 2 часа.

    +1

    Reply
  81. lesenoklenok

    Спасибо за пост! Если бы 1с сразу все делали оптимизированным, то не было бы столько критикующих за то что 1С тормозит. Некоторые запросы и куски кода можно было бы оптимизировать самому, но тогда начинаются проблемы с тем что в дальнейшем нужно конфигурацию обновить. И если текущий программист , который вносил изменения, сразу поймет, что этот кусок кода не стоит заменять на типовой, то другой пришедший программист на его место может не понять зачем эти изменения и при обновлении долго и мучительно думать стоит ли его заменить на типовой код или оставить. Вот по этому желательно чтобы 1С со своей стороны тоже оптимизировала старый код.

    Reply
  82. olbu

    Попробовал на тестовой (Файловый вариант) внести эти доработки, скорость даже визуально заметна… Попробовал добавить в рабочую SQL: все же время проведения уменьшилось…

    Reply
  83. hanio

    Именно частым обновлением статистики точечных регистров мы и спасались но все до поры до времени, сейчас буду пробовать ваш метод применить, спасибо за информацию.

    Reply
  84. djserega

    (61) Не будет ли проблем с одновременным проведением разных документов разными пользователями с одинаковыми товарами? Странно почему до сих пор 1С не переделало этот запрос… Наверное собака всё-таки где-то зарыта?!

    Reply
  85. Anzati

    может, кто подскажет по данному запросу, проблема такова:

    в консоли запросов этот запрос выполняется за 50 мс, при проведении РТиУ же строчка

    Возврат Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

    занимает порядка 40 секунд. Документ на 3 строчки. УТ 10.3, клиент-серверный вариант.

    Не могу понять, откуда такая разница во времени выполнения.

    Reply
  86. ZLENKO

    (86) Anzati, «Не могу понять, откуда такая разница во времени выполнения. »

    А если просто Возврат Запрос.Выполнить().Выгрузить(); ?

    Reply
  87. Anzati

    (87) ZLENKO.PRO, пробовал, разницы нет

    Reply
  88. Fominro

    Спасибо, способ помог. Действительно с 15 минут время проведения документа сократилось до одной минуты.

    Reply
  89. Silenser

    Пришлось на этой неделе озадачиться, т.к. проведение возвратов блокировало пользователей. Индексы были фрагментированы до 30%.

    Тоже пришел к выводу, что нужно оптимизировать запросы получения деревьев партий по УУ и БУ. Но я сделал в алгоритме отдельную веточку под наши параметры учета, чтобы не сильно корежить типовой алгоритм, заодно поменял систему поиска партий в функции ПолучитьСтрокуОстатковПартий, т.к. используемый метод НайтиСтроки — крайне медленный, переделал на поиск по индексированной строке (содержащей значения нескольких колонок) методом Найти. Получилось ускорить получение дерева УУ — на 43%, дерева БУ — на 3% (по сути в пределах погрешности, ну и нужно учитывать, что на создание временной таблицы нужно время), затраты на поиск строк улучшил на 81%. Отдал на тестирование в отдел сопровождения.

    Если ошибок в учете не найдут, опишу, что менял.

    Reply
  90. Wrols

    Антон, спасибо за публикацию!

    Вы пишите: «На текущий момент не рекомендуется использовать в запросе соединение с подзапросом».

    Поясните, пожалуйста, какая именно конструкция не рекомендуется

    Reply
  91. insurgut

    Ут 10.3, ордерная система, при проведении приходного ордера с видом операции Перемещение — выполнение запроса зависает.

    Интересно, что запрос:

    ВЫБРАТЬ
    *
    ПОМЕСТИТЬ СписанныеТовары
    ИЗ
    РегистрСведений.СписанныеТовары
    ГДЕ
    Регистратор В (&ОсновнойДокумент, &Ссылка)
    

    Показать

    в случае, когда ОсновнойДокумент <> Ссылка выполняется крайне долго.

    Сделал так:

    ВЫБРАТЬ
    *
    ПОМЕСТИТЬ СписанныеТовары
    ИЗ
    (ВЫБРАТЬ
    *
    ИЗ
    РегистрСведений.СписанныеТовары КАК СписанныеТовары
    ГДЕ
    СписанныеТовары.Регистратор = &ОсновнойДокумент
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    *
    ИЗ
    РегистрСведений.СписанныеТовары КАК СписанныеТовары
    ГДЕ
    СписанныеТовары.Регистратор = &Ссылка) КАК ВложенныйЗапрос
    
    ИНДЕКСИРОВАТЬ ПО
    Номенклатура

    Показать

    Конкретно этот кусок выполняется 36 тысячных секунды против 36 секунды для конкретного документа.

    Что я делаю не так? Возможно, что стоит чуть изменить код для при использовании ордерной системы, или приведенный мною код будет корректно работать и для случая, когда ОсновнойДокумент = Ссылка?

    Reply
  92. insurgut

    Очешуеть у меня после этого перепроведение партий полетело со скоростью космического корабля =)

    Все актуально для файловой базы, на сервере пока не тестировал.

    Reply
  93. insurgut
    Reply
  94. ZLENKO

    (94) insurgut,

    Я думаю проблемное место в «ПО СписанныеТовары.Регистратор = ПартииТоваровНаСкладах.Регистратор»

    Можно попробовать отобрать сначала в временную таблицу «ГДЕ ВозвратТоваровОтПокупателя.Товары.ДокументПартии = &ДокументПартии», а потом с ней соединять.

    Reply
  95. insurgut

    (95) ZLENKO, что-то вроде такого?

    ВЫБРАТЬ
    ВозвратТоваровОтПокупателя.Ссылка,
    ВозвратТоваровОтПокупателя.МоментВремени
    ПОМЕСТИТЬ Возвраты
    ИЗ
    Документ.ВозвратТоваровОтПокупателя КАК ВозвратТоваровОтПокупателя
    ГДЕ
    ВозвратТоваровОтПокупателя.Товары.ДокументПартии = &ДокументПартии
    И ВозвратТоваровОтПокупателя.МоментВремени > &МоментНач
    И ВозвратТоваровОтПокупателя.МоментВремени < &МоментКон
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ПартииТоваровНаСкладах.Номенклатура КАК Номенклатура,
    ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    ПартииТоваровНаСкладах.СерияНоменклатуры КАК СерияНоменклатуры,
    ПартииТоваровНаСкладах.ДокументОприходования КАК ДокументОприходования,
    ВЫБОР
    КОГДА ПартииТоваровНаСкладах.КодОперации = &ВозвратТекущегоМесяца
    ТОГДА -ПартииТоваровНаСкладах.Количество
    ИНАЧЕ ПартииТоваровНаСкладах.Количество
    КОНЕЦ КАК Количество,
    ВЫБОР
    КОГДА ПартииТоваровНаСкладах.КодОперации = &ВозвратТекущегоМесяца
    ТОГДА -ПартииТоваровНаСкладах.Стоимость
    ИНАЧЕ ПартииТоваровНаСкладах.Стоимость
    КОНЕЦ КАК Стоимость,
    ПартииТоваровНаСкладах.НомерСтрокиСписанныхТоваров
    ИЗ
    Возвраты КАК ВозвратыПокупателей
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СписанныеТовары КАК СписанныеТовары
    ПО (СписанныеТовары.Регистратор = ПартииТоваровНаСкладах.Регистратор)
    И (СписанныеТовары.ДокументПартии = &ДокументПартии)
    И (СписанныеТовары.НомерСтроки = ПартииТоваровНаСкладах.НомерСтрокиСписанныхТоваров)
    ПО (ПартииТоваровНаСкладах.Регистратор = ВозвратыПокупателей.Ссылка)

    Показать

    Reply
  96. ZLENKO

    (96) insurgut, «что-то вроде такого?»

    Ага. Я думаю там оптимизатор запроса спотыкается на составном типе при соединении.

    Reply
  97. insurgut

    (97) ZLENKO, нет, все-таки узкое место именно внутреннее соединение… Как бы отобрать записи регистров во временную таблицу только для регистраторов, которые мы получаем тут:

    ВЫБРАТЬ

    ВозвратТоваровОтПокупателя.Ссылка,

    ВозвратТоваровОтПокупателя.МоментВремени

    ПОМЕСТИТЬ Возвраты

    ИЗ

    Документ.ВозвратТоваровОтПокупателя КАК ВозвратТоваровОтПокупателя

    ГДЕ

    ВозвратТоваровОтПокупателя.Товары.ДокументПартии = &ДокументПартии

    И ВозвратТоваровОтПокупателя.МоментВремени > &МоментНач

    И ВозвратТоваровОтПокупателя.МоментВремени < &МоментКон
    Reply
  98. insurgut

    Итак, получил в итоге запрос, который выполняется 1,6 секунды против стандартного запроса, который выполняется 4,8 секунды:

    ВЫБРАТЬ
    ВозвратТоваровОтПокупателя.Ссылка,
    ВозвратТоваровОтПокупателя.МоментВремени
    ПОМЕСТИТЬ ВозвратТоваровОтПокупателя
    ИЗ
    Документ.ВозвратТоваровОтПокупателя КАК ВозвратТоваровОтПокупателя
    ГДЕ
    ВозвратТоваровОтПокупателя.Товары.ДокументПартии = &ДокументПартии
    И ВозвратТоваровОтПокупателя.МоментВремени > &МоментНач
    И ВозвратТоваровОтПокупателя.МоментВремени < &МоментКон
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    СписанныеТовары.Регистратор,
    СписанныеТовары.НомерСтроки
    ПОМЕСТИТЬ СписанныеТовары
    ИЗ
    РегистрСведений.СписанныеТовары КАК СписанныеТовары
    ГДЕ
    СписанныеТовары.ДокументПартии = &ДокументПартии
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ПартииТоваровНаСкладах.Номенклатура КАК Номенклатура,
    ПартииТоваровНаСкладах.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    ПартииТоваровНаСкладах.СерияНоменклатуры КАК СерияНоменклатуры,
    ПартииТоваровНаСкладах.ДокументОприходования КАК ДокументОприходования,
    ВЫБОР
    КОГДА ПартииТоваровНаСкладах.КодОперации = &ВозвратТекущегоМесяца
    ТОГДА -ПартииТоваровНаСкладах.Количество
    ИНАЧЕ ПартииТоваровНаСкладах.Количество
    КОНЕЦ КАК Количество,
    ВЫБОР
    КОГДА ПартииТоваровНаСкладах.КодОперации = &ВозвратТекущегоМесяца
    ТОГДА -ПартииТоваровНаСкладах.Стоимость
    ИНАЧЕ ПартииТоваровНаСкладах.Стоимость
    КОНЕЦ КАК Стоимость,
    ПартииТоваровНаСкладах.НомерСтрокиСписанныхТоваров
    ИЗ
    ВозвратТоваровОтПокупателя КАК ВозвратТоваровОтПокупателя
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ СписанныеТовары КАК СписанныеТовары
    ПО (СписанныеТовары.Регистратор = ПартииТоваровНаСкладах.Регистратор)
    И (СписанныеТовары.НомерСтроки = ПартииТоваровНаСкладах.НомерСтрокиСписанныхТоваров)
    ПО (ПартииТоваровНаСкладах.Регистратор = ВозвратТоваровОтПокупателя.Ссылка)

    Показать

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *