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

Публикация № 304912

Программирование - Практика программирования

регистры

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

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

 

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

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

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

 

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

 

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

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

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

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

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

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

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

            КонецЦикла;

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

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

 

 

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

 

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

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

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

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

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

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

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

                                        |ИЗ

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

                                        |ГДЕ

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

                                              

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

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

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

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

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

 

 

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

5

См. также

Специальные предложения

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


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


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

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


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

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


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

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


По сути не отличаются по скорости выполнения. Как следствие статья неочем :)
DrAku1a; Gureev; +2 Ответить
6. Yashazz 2375 30.09.14 14:14 Сейчас в теме
(4) Об чём я и говорил. Спасибо за подтверждение, мне было недосуг.

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

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

И ещё - дурное разыменование через пять точек при заполнении табчастей в цикле иногда виновато больше, нежели сам принцип заполнения.
5. Gilev.Vyacheslav 1823 30.09.14 14:01 Сейчас в теме
автор импирически уловил преимущества второго варианта, но не понял почему )))
объектная техника обращения точно так же делает запрос на уровне платформы, но только запрос более широкий, потому что читает все данные
особенно плохо это было на автоматических блокировках, так блокировалось больше чем надо
7. bulpi 150 01.10.14 14:38 Сейчас в теме
А еще умиляет вот это :
Движения.Остатки.Записать();

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


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