gifts2017

Формирование движений в регистрах и производительность системы 1С:Предприятие 8

Опубликовал Павел Дмитриев (pavel_D) в раздел Программирование - Практика программирования

Формирование движений в регистрах и производительность системы 1С:Предприятие 8

Формирование движений в регистрах и производительность системы 1С:Предприятие 8

 

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

Сравним два варианта записи движений в регистр накопления.

            Есть документ «Поступление»  с табличной частью «Товарыс реквизитами табличной части  «Товар» и  «Количество». Необходимо по каждой строчке из табличной части сделать приход в регистр накопления «Остатки».

 

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

 

Процедура ОбходомСтрок()

            Для Каждого Стр из Товары Цикл

                        Движение = Движения.Остатки.ДобавитьПриход();

                        Движение.Период = Дата;

                        Движение.Регистратор = Ссылка;

                        Движение.Товар = Стр.Товар;

                        Движение.Количество = Стр.Количество;

            КонецЦикла;

Движения.Остатки.Записать();

КонецПроцедуры

 

 

            И второй вариант, требующий знания механизма запросов .

 

Процедура Запросом()

 Запрос = Новый Запрос;

 Запрос.Текст = "ВЫБРАТЬ

                                       |       ПриходТовары.Товар,

                                       |       ПриходТовары.Количество,

                                       |       ПриходТовары.Ссылка КАК Регистратор,

                                       |       ПриходТовары.Ссылка.Дата КАК Период

                                        |ИЗ

                                        |      Документ.Приход.Товары КАК ПриходТовары

                                        |ГДЕ

                                        |      ПриходТовары.Ссылка = &Ссылка";

                                              

Запрос.УстановитьПараметр("Ссылка",Ссылка);

ТЗ = Запрос.Выполнить().Выгрузить();

Движения.Остатки.Загрузить(ТЗ);

Движения.Остатки.Записать();     

КонецПроцедуры

 

 

Формирование движений в регистре с использованием второго варианта происходит значительно быстрее, чем при использовании первого варианта. Замеры производительности при отладке дают прирост скорости от 30 %

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Артем Целовальников (slazzy) 30.09.14 09:27
Это правда достойно отдельной статьи? Если уж на то пошло, то зачем выбирать в запросе регистратор и дату, если у нас и так доступен объект.
На каком основании вы делаете вывод, что запрос быстрее? Данные объекта уже в оперативной памяти, а запрос читает из базы данных.
Запрос в данном случае используется во много для удобной манипуляции данными, например чтобы сгруппировать дубли(чего вы не сделали) или отсечь услуги, например.


Очень жаль, что нельзя ставить минус. Это один из тех примеров, когда минус за статью был бы заслужен.
i_lo; suggestive; Tavalik; bulpi; Yashazz; +5 Ответить 2
2. Юрий Гончарук (yukon) 30.09.14 10:10
(1) slazzy,
На каком основании вы делаете вывод, что запрос быстрее?


Вроде автор написал: "Замеры производительности при отладке дают прирост скорости от 30 %". Этого недостаточно?

Данные объекта уже в оперативной памяти, а запрос читает из базы данных.


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

В целом, если еще избавится от промежуточной таблицы значений, а загружать движения сразу из результата запроса, то вообще было бы отлично.
3. Яков Коган (Yashazz) 30.09.14 12:09
Согласен с (1), это как-то совсем обрывочно и куце.
Кроме того, есть и промежуточные варианты - например, вываливание табчасти в таблицу значений и обход циклом уже в ней.
Ну и, автор, зачем вы выбираете в запросе "Период" и "Регистратор", кои одинаковы по определению во всех строках выборки? А если у вас документ из сотен строк? Проще ведь дозабить напрямую в наборе.
Зачем промежуточная таблица значений, которая будет занимать место в оперативке?

Гораздо интереснее, если бы вы рассказали, например, об особенностях кэширования результатов запроса, особливо о разнице между выгрузкой в таблицу значений и в ОбходРезультатаЗапроса, и о разнице в применении этих объектов к заполнению движений.

И ещё - дурное разыменование через пять точек при заполнении табчастей в цикле иногда виновато больше, нежели сам принцип заполнения.
4. Артем Целовальников (slazzy) 30.09.14 13:50
(2) yukon,
Проблема не в наличии объекта в оперативной памяти, а в скорости перебора табличной части vs. формирования единой таблицы значений.


Проблема в том, что это в корне меняет смысл статьи. Вся разница достигается не за счет "скорости запроса", которая якобы постулируется, а просто за счет того, что перебор делается дольше, чем выгрузка/загрузка. Что по большому счету никак не связано с методом получения данных, мы ведь можем выгрузить/загрузить из табличной части.
Сейчас протестировал:
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ДокументТовары.Номенклатура,
		|	ДокументТовары.Количество
		|ИЗ
		|	Документ.Документ.Товары КАК ДокументТовары
		|ГДЕ
		|	ДокументТовары.Ссылка = &Ссылка";
	
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	
	Движения.Регистр.Загрузить(Запрос.Выполнить().Выгрузить());
...Показать Скрыть

	ТЧ = Товары.Выгрузить();
	ТЧ.Колонки.Добавить("Период");
	ТЧ.ЗаполнитьЗначения(Дата,"Период");
	Движения.Регистр.Загрузить(ТЧ);
...Показать Скрыть


По сути не отличаются по скорости выполнения. Как следствие статья неочем :)
DrAku1a; Gureev; +2 Ответить 1
5. Вячеслав Гилёв (Gilev.Vyacheslav) 30.09.14 14:01
автор импирически уловил преимущества второго варианта, но не понял почему )))
объектная техника обращения точно так же делает запрос на уровне платформы, но только запрос более широкий, потому что читает все данные
особенно плохо это было на автоматических блокировках, так блокировалось больше чем надо
6. Яков Коган (Yashazz) 30.09.14 14:14
(4) Об чём я и говорил. Спасибо за подтверждение, мне было недосуг.

(5) Вячеслав, это как? Речь ведь об одном документе, точнее, о строках из табличной части, которые к нему относятся. Ты хочешь сказать, что там безотносительно объектной блокировки лочилась вся таблица табчасти? Или ты о движениях?
7. bulpi bulpi (bulpi) 01.10.14 14:38
А еще умиляет вот это :
Движения.Остатки.Записать();

Так набор запишется 2 раза :)
arnautov.eugene; +1 Ответить 1
8. Константин Юрин (kostyaomsk) 01.10.14 18:26
Данные вопросы звучат на собеседованиях для специалистов 1С по оптимизации :)
9. Евгений Арнаутов (arnautov.eugene) 26.02.15 14:14
(7) bulpi, Ну и выгрузка в таблицу значений доставляет. Вроде, уже везде говорили, что выборка - предпочтительнее, поскольку не грузит в ОЗУ сразу весь результат целиком (по 25 строк). В котором к тому же и записи не сгруппированы и услуги не убраны, как заметил slazzy. В принципе, если всю базу загрузить на RAM - диск - тоже получим гарантированный прирост производительности.
10. ZLENKO.PRO (ZLENKO) 26.02.15 14:19
Движения.Остатки.Записать(); 


Это в любом случае неправильно. Явная запись движений может приводить к взаимоблокировкам.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа