Боремся с запросами в циклах. Мой опыт рефакторинга запросов

02.03.20

Разработка - Рефакторинг и качество кода

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

 

Введение. Цель статьи

Привет всем! В настоящей статье я хочу затронуть такую злободневную тему как "запросы в цикле". Наверное, нет ни одного программиста 1с, который бы не использовал хоть раз запрос в цикле, а некоторые (и их очень много) считают это даже нормой программирования. Ну а что, многие могут подумать, раз свою задачу программа выполняет - можно и использовать - пользователи ведь довольны результатом и принимают его. И таких "отчетов" я встречал, ну наверное 70 - 80%..... как бы это было не печально или смешно.

Но, исходя из своей практики и опыта, однажды до меня "дошло", что использование запросов в цикле - это все-таки не такая уж универсальная и правильная штука и, в этой статье, я постараюсь объяснить на примерах почему, постараюсь показать на практике.

Понятно, что каждый "начинающий" программист, который умеет "собирать" колонки в таблице результата (например, для СКД) считает, что может построить любой отчет или обработку.

Отчасти это так. И вопрос как долго по времени будут "собираться данные в таблицу результата" - отнюдь не самый главный здесь. На ИТС, в разделе "оптимизация запросов" написано примерно так - что нужно не только добиваться поставленной цели, но и обеспечить комфорт и скорость работы пользователей с ним. Я с этим согласен полностью. Но это про каких-то там пользователей.... "пусть ночью запускают" - ответ "программистов", которые не могу совладать с оптимизацией.....

Я бы предложил свой аргумент, гораздо более весомый, подкрепленный моим практическим опытом, на мой взгляд - если программист привык "собирать" данные, используя запросы в цикле, то в плане развития, он никогда не научится решать более сложный класс задач, где использование запросов в цикле просто невозможно. Посмотрим какие задачи в этой статье дальше.

В статье я упомяну конфигурации Управление торговлей 10.3 и Розница 2.3. Задачи решались на платформе 8.3.15.1830.

 

Когда бы я использовал "запрос в цикле"

Странный раздел, да? Попробую объяснить вам почему я так назвал его. На примере. Была у меня как-то задачка лет 7 назад, где нужно было построить "своеобразный" АВС-анализ, который в корне отличался от типового. Это была достаточно большая городская розничная сеть, которая работала на УТ 10.3. Управляющая сама не знала, чего ей нужно, но "за первый заход" (конечно это был не совсем первый заход) нарисовала вот такую таблицу - "нужно мол вот так":

 

Рис.1. "Первоначальная таблица" АВС-анализа.

 

Ну как? Просто? Сейчас, возможно, да -  это ведь обычные данные для "торгового" отчета - "производственные" таблицы "план/факт" в разы сложнее. С ними я тоже имел дело, работая в УПП, но не буду их касаться здесь.

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

 

Рис.2. Выбор алгоритма расчета себестоимости.

 

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

Как я подошел к решению данной задачи - воспользовался определенным правилом и вынес все "расчетные и получаемые величины" в свои собственные  функции.

Изначально, я постарался оптимизировать свое личное время разработки данного отчета.

Первым шагом, я создал основной "базовый" простейший запрос. Пусть он будет вот такой:

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

СГРУППИРОВАТЬ ПО
	ПродажиОбороты.Номенклатура,
	ПродажиОбороты.Подразделение,
	ПродажиОбороты.ДокументПродажи.Склад,
	ПродажиОбороты.Организация,
	ПродажиОбороты.ДокументПродажи.Дата

 

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

Рис.3. Набор внешних функций для определения необходимых величин.

 

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

Функция ВаловаяПрибыль(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат ВаловаяПрибыльРезультат;
	
КонецФункции

Функция КолвоМагазинов(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат КолвоМагазиновРезультат;
	
КонецФункции

Функция Поставщик(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат ПоставщикРезультат;
	
КонецФункции

Функция ПоследнийЗакуп(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат ПоследнийЗакупРезультат;
	
КонецФункции

Функция Выручка(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат ВыручкаРезультат;
	
КонецФункции

Функция ЧистаяПрибыль(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат ЧистаяПрибыльРезультат;
	
КонецФункции

Функция Списание(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***

	Возврат СписаниеРезультат;
	
КонецФункции

Функция СредняяЦенаПродажи(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***
	
	Возврат СредняяЦенаПродажиРезультат;
	
КонецФункции

Функция Наценка(Номенклатура, Дата) Экспорт
	
	//*** Содержимое функции ***
	
	Возврат НаценкаРезультат;
	
КонецФункции

 

Ну и в вынесенных функциях "я творил что угодно" : подгонял их под быстро-меняющиеся условия данной задачи. После того как результаты отчета были удовлетворительные, я немного оптимизировал данное решение ("а теперь попробуй его убыстрить" - меня так попросили) - получая некоторые величины сразу в запросе.

 

Небольшая по-шаговая оптимизация отчета

В этом разделе я приведу пример "оптимизации" функции получение последнего поставщика. Допустим, в вышеупомянутой функции я использовал "запрос в цикле", выбирал первого поставщика по номенклатуре и упорядочивал по дате убывания в возвращал в таблицу для СКД. В противовес этому запросу я буду использовать функцию языка запросов МАКСИМУМ. Наверное, в 80% я использую данный механизм, чтобы избежать запроса в цикле.

Запрос по определению поставщика номенклатуры выглядит вот так:

ВЫБРАТЬ
	МАКСИМУМ(Закупки.Период) КАК Период,
	Закупки.Номенклатура КАК Номенклатура
ПОМЕСТИТЬ ВТ_Номенклатура
ИЗ
	РегистрНакопления.Закупки КАК Закупки

СГРУППИРОВАТЬ ПО
	Закупки.Номенклатура

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Закупки.Номенклатура,
	МАКСИМУМ(Закупки.Контрагент) КАК Контрагент,
	Закупки.Период КАК Период
ИЗ
	РегистрНакопления.Закупки КАК Закупки
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Номенклатура КАК ВТ_Номенклатура
		ПО Закупки.Номенклатура = ВТ_Номенклатура.Номенклатура
			И Закупки.Период = ВТ_Номенклатура.Период

СГРУППИРОВАТЬ ПО
	Закупки.Номенклатура,
	Закупки.Период

 

Объясню запрос - первым шагом я выбираю Максимальную дату "Период" поступления номенклатуры на склад  в регистре накопления "Закупки" по этой номенклатуре (это одна запись). А вторым шагом - я выбираю "Максимального" (в данном случае - единственного поставщика), в периоде времени по этой номенклатуре. Почему максимального - потому, что могут быть поступления по одной номенклатуре в одну дату и одно время. Это неоднозначность - исключается так же функцией МАКСИМУМ.

Вот так - Играясь с измерениями по Периоду регистра накопления "Закупки" (используя функцию МАКСИМУМ), я создал нужную мне временную таблицу, которую я соединю с "базовым" запросом.

Теперь, я могу исключить внешнюю функцию "Поставщик". Вот примерно таким способом, я стараюсь оптимизировать (ускорить) уже готовое решение.

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

 

Когда использование исключено

После моего небольшого примера по оптимизации, постараюсь написать почему нужно избавляться от практики "запросов в цикле". Вот явный аргумент - -объект "динамический список", который очень часто используется в современных конфигурациях, в основе которого чаще всего лежит "произвольный запрос" и как бы не пытался - за один "присест" мне в динамическом списке необходимо собрать все данные одним запросом.

Вот пример. Конфигурация "Розница", справочник "Номенклатура", изначальное содержание динамического списка вот такое:

ВЫБРАТЬ
	СправочникНоменклатура.Ссылка КАК Ссылка,
	СправочникНоменклатура.Код КАК Код,
	СправочникНоменклатура.Наименование КАК Наименование,
	СправочникНоменклатура.ВидНоменклатуры КАК ВидНоменклатуры,
	СправочникНоменклатура.ТоварнаяКатегория КАК ТоварнаяКатегория,
	СправочникНоменклатура.Марка КАК Марка,
	ВЫБОР
		КОГДА СправочникНоменклатура.ЭтоГруппа
			ТОГДА ВЫБОР
					КОГДА СправочникНоменклатура.ПометкаУдаления
						ТОГДА 7
					ИНАЧЕ 6
				КОНЕЦ
		ИНАЧЕ ВЫБОР
				КОГДА СправочникНоменклатура.ПометкаУдаления
					ТОГДА 1
				ИНАЧЕ 0
			КОНЕЦ + ВЫБОР
				КОГДА СправочникНоменклатура.ВидНоменклатуры.ИспользованиеХарактеристик = ЗНАЧЕНИЕ(Перечисление.ВариантыВеденияДополнительныхДанныхПоНоменклатуре.НеИспользовать)
					ТОГДА 0
				ИНАЧЕ 2
			КОНЕЦ
	КОНЕЦ КАК ИндексКартинки,
	СправочникНоменклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
	СправочникНоменклатура.Артикул КАК Артикул,
	СправочникНоменклатура.НаименованиеПолное КАК НаименованиеПолное,
	СправочникНоменклатура.Вес КАК Вес,
	СправочникНоменклатура.СтавкаНДС КАК СтавкаНДС,
	СправочникНоменклатура.ТипНоменклатуры КАК ТипНоменклатуры,
	ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
	Справочник.Номенклатура КАК СправочникНоменклатура
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ТекДата, ) КАК ТоварыНаСкладахОстатки
		ПО СправочникНоменклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура

 

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

ВЫБРАТЬ
	НоменклатураПоставщиков.Номенклатура КАК Номенклатура,
	МАКСИМУМ(НоменклатураПоставщиков.ДатаПоследнегоПоступления) КАК ДатаПоследнегоПоступления
ПОМЕСТИТЬ ДатаПоступленияТаб
ИЗ
	РегистрСведений.НоменклатураПоставщиков КАК НоменклатураПоставщиков

СГРУППИРОВАТЬ ПО
	НоменклатураПоставщиков.Номенклатура

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	МАКСИМУМ(НоменклатураПоставщиков.Поставщик) КАК Поставщик,
	НоменклатураПоставщиков.Номенклатура КАК Номенклатура,
	НоменклатураПоставщиков.ДатаПоследнегоПоступления КАК ДатаПоследнегоПоступления
ПОМЕСТИТЬ ВТ_Поставщики
ИЗ
	ДатаПоступленияТаб КАК ДатаПоступленияТаб
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НоменклатураПоставщиков КАК НоменклатураПоставщиков
		ПО ДатаПоступленияТаб.Номенклатура = НоменклатураПоставщиков.Номенклатура
			И ДатаПоступленияТаб.ДатаПоследнегоПоступления = НоменклатураПоставщиков.ДатаПоследнегоПоступления

СГРУППИРОВАТЬ ПО
	НоменклатураПоставщиков.Номенклатура,
	НоменклатураПоставщиков.ДатаПоследнегоПоступления

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	СправочникНоменклатура.Ссылка КАК Ссылка,
	СправочникНоменклатура.Код КАК Код,
	СправочникНоменклатура.Наименование КАК Наименование,
	СправочникНоменклатура.ВидНоменклатуры КАК ВидНоменклатуры,
	СправочникНоменклатура.ТоварнаяКатегория КАК ТоварнаяКатегория,
	СправочникНоменклатура.Марка КАК Марка,
	ВЫБОР
		КОГДА СправочникНоменклатура.ЭтоГруппа
			ТОГДА ВЫБОР
					КОГДА СправочникНоменклатура.ПометкаУдаления
						ТОГДА 7
					ИНАЧЕ 6
				КОНЕЦ
		ИНАЧЕ ВЫБОР
				КОГДА СправочникНоменклатура.ПометкаУдаления
					ТОГДА 1
				ИНАЧЕ 0
			КОНЕЦ + ВЫБОР
				КОГДА СправочникНоменклатура.ВидНоменклатуры.ИспользованиеХарактеристик = ЗНАЧЕНИЕ(Перечисление.ВариантыВеденияДополнительныхДанныхПоНоменклатуре.НеИспользовать)
					ТОГДА 0
				ИНАЧЕ 2
			КОНЕЦ
	КОНЕЦ КАК ИндексКартинки,
	СправочникНоменклатура.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
	СправочникНоменклатура.Артикул КАК Артикул,
	СправочникНоменклатура.НаименованиеПолное КАК НаименованиеПолное,
	СправочникНоменклатура.Вес КАК Вес,
	СправочникНоменклатура.СтавкаНДС КАК СтавкаНДС,
	СправочникНоменклатура.ТипНоменклатуры КАК ТипНоменклатуры,
	ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток,
	ВТ_Поставщики.Поставщик КАК Поставщик,
	ВТ_Поставщики.ДатаПоследнегоПоступления КАК ДатаПоследнегоПоступления
ИЗ
	Справочник.Номенклатура КАК СправочникНоменклатура
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ТекДата, ) КАК ТоварыНаСкладахОстатки
		ПО СправочникНоменклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Поставщики КАК ВТ_Поставщики
		ПО СправочникНоменклатура.Ссылка = ВТ_Поставщики.Номенклатура

В этом примере, я вынужден сделать все в одном запросе, сразу исключив всякие неудобно-сомнительные конструкции типа "внешних функций" и "запросов в цикле"

 

Выводы

 

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

Я описал свою рабочую практику - это мой личный практический опыт. Применять его вам или нет - это ваш выбор и желание.

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

Так же, в данный статье, я постарался объяснить и показал на практике, что правильное изучение механизмов запросов 1с и исключение из своей практики "запросов в цикле" поможет вам собирать и корректировать такой функционал платформы как "динамические списки". А без "динамических списков" сейчас не обходится ни одна современная конфигурация на управляемых формах.

Всем спасибо. Всем привет и до новых встреч!

 

Предыдущие материалы

Так же, я прошу посмотреть мои предыдущие статьи:

Динамический список. Апгрейд справочника "Номенклатура" типовой конфигурации с помощью расширения

Лайфхак работы с СКД. Собираем отчет

СКД. Лайфхак №2. Собираем отчет еще удобнее

СКД. Шаг 3. Используем макеты для оформления отчета

Обсудим планы обмена. Способы регистрации объектов к обмену

1С + IIS + SSL: Перевод опубликованной базы на защищенное соединение https с сертификатом от Let's encrypt

запрос в цикле временные таблицы максимум минимум

См. также

Когда понадобился новый оператор

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда понадобился новый оператор, но его нет в синтакс-помощнике, что делать?

18.03.2024    1138    ZhokhovM    2    

4

Когда разработчик платформы не добавил проверку препроцессоров

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда разработчик платформы решил пойти на кухню за кофе, а проверку препроцессоров не добавил, и вот тут-то и началось: "Что, опять все сломалось? Ну и кофе же я забыл сделать!".😅

18.03.2024    2669    ZhokhovM    4    

8

Реструктуризация - бесконечная история

Рефакторинг и качество кода Платформа 1С v8.3 Бесплатно (free)

При разработке программ требуемый функционал ставят на первое место, но есть еще и архитектура программы. На горизонте 5-10 лет она становится важнее функционала, который должен работать при масштабировании и росте данных. Реструктуризация 5 терабайтной базы 1С 8.2 в формат 1С 8.3, складывает весь пазл архитектурных просчетов, которые сделали ради функционала. Как это исправить? - для разработки правильной архитектуры, нужно всего лишь сместить фокус с функционала и подумать о «вечном».

29.09.2023    1907    1CUnlimited    15    

22

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 2

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

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

27.09.2023    6965    Lemmonbri    136    

36

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 1

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

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

19.09.2023    4344    Lemmonbri    16    

31

5 подходов при доработке конфигурации 1С, чтобы в будущем не было мучительно больно её обновлять

Архитектура Рефакторинг и качество кода Обновление 1С Платформа 1С v8.3 Бесплатно (free)

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

10.08.2023    9581    0    1c-izhtc    37    

21

Задача на ошибки и неоптимальности при проведении приходной накладной

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Задачу эту дают на собеседованиях, видимо, те франчи, которые не в состоянии оценить человека по резюме и в ходе беседы. По идее задачи, подобные этой, должны давать начинающим студентам. Но дают всем подряд. Итак: мои 5 копеек. Критика приветствуется.

11.07.2023    2214    magic1s    32    

11
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. AlexPC 02.03.20 11:31 Сейчас в теме
Какой смысл в индексации ВТ_Поставщики по полю Поставщик? В соединениях оно нигде не используется.
2. aximo 2027 02.03.20 12:33 Сейчас в теме
(1) всегда индексирую большие временные таблицы по «измерениям» , но если в данном примере - никакого
hlopotov1993; +1 3 Ответить
3. nomad_irk 71 02.03.20 12:36 Сейчас в теме
(2)для чего индексировать ВСЕГДА?
4. herfis 498 02.03.20 12:41 Сейчас в теме
(3) Видимо из серии "хуже не будет" :) Я на практике никогда существенного влияния индексации временных таблиц на время выполнения не замечал. Но самое смешное, что на практике я также никогда не замечал прироста производительности от индексации временных таблиц. Но на всякий случай все-таки индексирую по полям соединения, когда соединяются тяжелые таблицы.
DrAku1a; acanta; +2 Ответить
9. &rew 49 02.03.20 13:04 Сейчас в теме
(4)Ваял на СКД однажды "расческу" из временных таблиц. Так прирост был очень ощутимый. Прям ОЧЕНЬ.
20. Sapiens_bru 4 03.03.20 04:50 Сейчас в теме
(4) Лично ускорял отчёт с 12 секунд до 0.4 секунды, добавив только индексы одной временной табличке. Раз на раз не приходится.
Вообще без нужды индексы не добавляю, а если и делаю то после добавления индекса сбрасываю процедурный кэш на сервере и смотрю профайлером - используется ли новый индекс.
5. aximo 2027 02.03.20 12:49 Сейчас в теме
(3) как раз для того, что возможно потом будет использование этих временных таблиц в других соединениях. работали с производственными отчетами?
6. nomad_irk 71 02.03.20 12:55 Сейчас в теме
(5)Так программист должен четко понимать, будет данная таблица использоваться в соединениях/в этой таблице отбор или не будет, и в зависимости от этого выполнять индексацию или нет. Включать индексацию ВСЕГДА, да еще и на больших таблицах - по крайней мере, глупо.
kaaasteeen; chilyagin; brr; Vladimir Litvinenko; leongl; Yashazz; +6 1 Ответить
8. aximo 2027 02.03.20 13:03 Сейчас в теме
(6) вот кстати, на ИТС написано с точностью наоборот "Для быстрого получения нужной записи из таблицы, в которой могут быть тысячи, десятки тысяч и миллионы записей, также требуется индекс, наиболее полно и точно описывающий, как эту запись найти. Поиск по индексу позволяет максимально быстро получить требуемые данные." https://its.1c.ru/db/metod8dev#content:5842:hdoc
11. nomad_irk 71 02.03.20 13:07 Сейчас в теме
(8)Так индекс должен быть соответствующий требованиям поиска, а не абы какой. Индекс по всем "измерениям" ВСЕГДА - вообще не факт, что будет этим требованиям соответствовать. В итоге - потратили время и ресурсы на создание и поддержание индекса, но он не используется.
VitaliyCeban; brr; Yashazz; Vladimir Litvinenko; leongl; +5 Ответить
14. Vladimir Litvinenko 2869 02.03.20 18:02 Сейчас в теме
(11) Ох, тоже хотел много написать на эту тему и в частности об использовании временных таблиц в динамическом списке (в том виде, в котором они здесь представлены) и накладных расходах на создание индексов с конкретными примерами. Но вспомнил последнюю дискуссию относительно СКД https://infostart.ru/public/1200689 и что-то передумал )) Боюсь такое "код-ревью" не встретило бы понимания в описываемых условиях разработки.

Автор описывает вообще опыт разработки под высоким давлением заказчика и очевидно на небольшом объеме данных. Потому что на большом объеме такие запросы вообще бы не взлетели - две временные таблицы в динамическом списке по большим таблицам да ещё и с агрегацией и последующим построением неиспользуемых кластерных индексов (наверняка там MS SQL) - это более чем дорогая штука.

В таких условиях советовать то что-либо бесполезно и индексация временных таблиц далеко не главная проблема ))

Интересно, что бы сказал автору заказчик, если бы заказчику было предложено адекватное решение - вывод данных по номенклатуре в отдельных полях на форме с некоторой паузой после активизации строки?
16. Yashazz 4709 02.03.20 18:08 Сейчас в теме
(14) Владимир, есть подозрение, что поведение ВТ в динамических списках ещё не устаканено и 1С будет его допиливать. У меня есть странные и труднообъяснимые результаты замеров на разных релизах, с 8.3.9 по 8.3.13, с колебаниями производительности в обе стороны; думаю, делать выводы по дин.спискам ещё рано.
17. Vladimir Litvinenko 2869 02.03.20 18:16 Сейчас в теме
(16) Здесь дело в том, какой объем данных помещается в эти временные таблицы. В данных примерах выбирается справочник целиком, затем происходит агрегация. Так как список динамический c динамическим считыванием данных, то при каждом следующем запросе (пролистывании списка) платформа 1С не может полагаться на ранее полученные данные и снова инициирует сканирование всей таблицы средствами СУБД.

А дальше ещё одна таблица строится с агрегацией. Здесь дело не в особенностях релиза будет, а в том, что реляционная СУБД физически не сможет нормально это обрабатывать.

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

Это кстати хорошо соотносится с вопросом обсуждаемым здесь )) https://infostart.ru/journal/news/mir-1s/opros-soobshchestva-razrabotchikov-na-1s_1202988/
19. Yashazz 4709 02.03.20 18:28 Сейчас в теме
24. RustIG 1351 04.03.20 06:58 Сейчас в теме
(6) мы не знаем реальную задачу, в публикации приведен "концепт", и он не связан с индексацией Поставщика. Пример вырван из контекста, поэтому допустимы погрешности в таких деталях. В статье , кстати, четко описана ситуация по то, что ситуация изменяется постоянно, техзадание не стабильно, а вы вешаете ярлык
программист должен четко понимать, будет данная таблица использоваться
28. nomad_irk 71 04.03.20 08:27 Сейчас в теме
(24)Речь не про концепт и не пример из статьи, речь про "всегда индексирую большие временные таблицы по «измерениям»".
29. RustIG 1351 04.03.20 08:36 Сейчас в теме
(28) ну вы зацепились за слова... у него опыт такой, что он "почти всегда делает это на своей базе".... в другой фирме на другой базе он столкнется с другой задачей... изменит сове отношение... в чем польза раскручивать человека за сказанное? опишите свой опыт или свое видение... не знаю, сделайте шаг навстречу что ли...
7. user660153_aleks.pisanets 113 02.03.20 12:57 Сейчас в теме
.Так же, напишу еще раз здесь, что являюсь сторонником красивых решений задач. Красивое решение задачи - это решение, где единым запросом, получаем всю таблицу необходимых данных сразу на 100%, а затем "оформляем"
- а как же злосчастные многоэкранные запросы с кучей вложенных таблиц,вычислений и всего прочего...? Обычно на отладку которых уходит несколько дней. Я бы не назвала их "красивыми", вполне можно собрать итоговую таблицу и из более мелких,но более читаемых и лёгких в сопровождении запросов, при этом не используя цикл в цикле) Но это лично мое мнение))
lefthander; RustIG; +2 1 Ответить
10. aximo 2027 02.03.20 13:06 Сейчас в теме
(7) красивое решение - это решение, когда получаешь все необходимые данные в запросе за один заход. можно разделить работу - один программист "рисует запросы", другой - оформляет их...
12. user660153_aleks.pisanets 113 02.03.20 13:29 Сейчас в теме
(10)я не о разделении труда говорю, а о последующем сопровождении "красивых" запросов. Вырвиглазных...ну да ладно, мы друг друга просто не поняли
26. RustIG 1351 04.03.20 07:19 Сейчас в теме
(7) поддержу вас! :)
в свое время написал статью про "большие запросы" - посыл в ней простой - выделить показатели, для показателей создать отдельные регистры, пересчитывать показатели в отдельных процедурах, формировать (собирать) итоговый отчет по показателям по периодам во всех разрезах по одной результирующей таблице (аналог куба) https://infostart.ru/public/195627/
мысль в статье описана сложно - не идеал, и сейчас бы я написал по другому... - что-то подобное позже я стал встречать в типовых конфигурациях...
13. Yashazz 4709 02.03.20 13:29 Сейчас в теме
1. Аргументы внешних функций тоже можно по-умному кэшировать, если понимать разницу между вынесением логики обработки данных и вынесением получения данных.
2. Кроме логики "запрос в цикле" и "запрос перед циклом в некую коллекцию", есть ещё масса способов.
3. Насчёт индексации ВТ уже сказали, поддерживаю.
4. Красивое - это не когда "за один заход", а когда оно модульное, прозрачное, оптимальное и по ресурсам, и по бизнес-логике.

ну и наконец - динамические списки это вообще отдельный разговор
wolfsoft; Summer_13; purgin; awk; Климов Сергей; user660153_aleks.pisanets; +6 Ответить
15. Yashazz 4709 02.03.20 18:05 Сейчас в теме
А, так это автор позора под названием "лайфхак по СКД", ааа, ну да, да... Тогда и уход от запроса в цикле описанным способом - уже величайшее достижение и полёт мысли...
wolfsoft; +1 Ответить
30. serko8547 110 04.03.20 14:59 Сейчас в теме
(15)
о автор позора под названием "лайфхак по СКД", ааа, ну да, да... Тогда и уход от запроса в цикле описанным способом - уже величайшее достижение и полёт мысли...

ну, каждый программирует - как умеет!
ошибся однажды - не стоит его за гнобить всю жизнь!
32. Yashazz 4709 04.03.20 22:31 Сейчас в теме
(30) Программировать - это завсегда. А вот зачем это публиковать, я не понимаю. Ну я злой, да.
18. acanta 02.03.20 18:27 Сейчас в теме
В 7ке была рекомендация не превышать определенное количество строк в табличной части документа, поскольку время записи документа в зависимости от количества строк сначала растет линейно, а затем экспоненциально. А как в 8ке, в табчастях, таблицах значений - где-то мелькало здесь? В дбф 7.7 было похоже в sql и файловой не видела. Ожегшись на молоке, алгоритмы делаю для ограничения по количеству строк машинально, бывает и запрос в цикле пишу. И даже в двойном цикле, как в фокспро. Вероятно запросы следует изучить получше, Хрусталеву почитать.
Но если нужно разделить данные на несколько частей неважно, разного или фиксированного размера, запросом придется получать весь объем и делить его программно, а это другие обьекты, не выборка из результатов запроса.
21. &rew 49 03.03.20 06:28 Сейчас в теме
(18)Помню на 7ке сворачивал базу, т.к. разраслась более 2гб таблица. Сворачивалась долго и упорно стандартной сверткой, пока не ограничил количество строк 1000 записями. Причем свертка стандартная.
(18)
В 7ке была рекомендация не превышать определенное количество строк в табличной части документа, поскольку время записи документа в зависимости от количества строк сначала растет линейно, а затем экспоненциально.

Вот об этой рекомендации я не знал.
33. Yashazz 4709 04.03.20 22:34 Сейчас в теме
(18) Кстати, о "двойном цикле" - ненуачо, nested loops сильно от этого ушёл? Иногда эмулировать даже и дешевле выйдет, чем ждать милости от хз какой статистики вкупе с сумасбродным оптимизатором.
22. zodus 67 03.03.20 11:53 Сейчас в теме
Лепил раз по примеру внешних функций, регламентированный отчет 0503190 в бгу , 1сы на край отказались делать заполнение ее, было осуществлено через множество функций еще и через рекурсию, это очень быстрый метод по времени показался и простой в отладке и за день сделал из за своей лени потом поплатился, формировался отчет примерно до 5 минут, потом сделал все одним запросом через СКД, формирует почти моментально 10-15 сек от силы) Вывод нужно не лениться и делать уже нормально, когда понял, что код не очень твой)
25. RustIG 1351 04.03.20 07:12 Сейчас в теме
(22) у вас выводы на всю жизнь по одной вашей ситуации?....:(
у меня опыт другой: и рекурсию, и запросы в цикле - все можно использовать, при отладке надо делать замеры производительности, отлаживать надо не только в тестовой копии, где данных мало, а также на рабочих базах с большим кол-вом записей. При этом отлаживать = включает в себя обязательный замер производительности. Многие разработчики отлаживают без замеров производительности или только на своих копиях....
34. zodus 67 10.03.20 09:38 Сейчас в теме
(25) спорить не буду исходя из с# что иногда и рекурсия бывает быстрее линейных уравнений все зависит от объема обрабатываемых данных, в 1с просто все рекомендация, что я встречал были отказаться от циклов в цикле, а так конечно все через замеры
23. RustIG 1351 04.03.20 06:53 Сейчас в теме
(0) Спасибо за статью! +

Спасибо, что дочитали данную спорную статью до выводов.

Статья реально дискуссионная (спорная, но спорить не будет...поэтому дискуссионная :) )

Вопросы:
1) Правильно, я понимаю, что Максимум по Контрагенту выдаст того же самого Контрагента? То есть не приходится выбирать контрагентов из списка других - во всех записях отобранных по периоду и номенклатуре один и тот же контрагент. Мы просто схлопываем записи в одну... Верно?

2) Картинки представлены из конфигруации по обычным формам, в конце статьи выруливаете на управляемые формы.... Как так?

3) Про запросы в цикле - я бы не писал так однозначно ,что использовать их нельзя. В некоторых ситуациях они необходимы. Просто программистам надо всегда понимать и помнить о производительности алгоритма и том выигрыше, который дает или не дает та или иная конструкция языка программирования...
27. RustIG 1351 04.03.20 07:25 Сейчас в теме
(0) 1. на заметку
запрос в цикле + красивое решение = https://infostart.ru/public/1043307/

понятно, что к вашему решению подобное не относится... при решении задачи нельзя использовать универсальные решения, надо отталкиваться от ТЗ, ТЗ со временем меняется... поэтому решение постоянно меняется, переписывается...

2. на заметку как я добавил доп.показатели в УТ 10.3, не используя большие запросы и циклы https://infostart.ru/public/1054542/
31. Yashazz 4709 04.03.20 22:30 Сейчас в теме
У меня бывали случаи, когда запрос в цикле выигрывал по сравнению с другими способами. Рустем совершенно прав, нет и не может быть "единого супер-пупер рецепта". Сколько копий сломали про индексацию временных таблиц, к примеру)) Надо уметь смотреть и думать, а не носиться слепо с одним, единожды самостоятельно найденным или у некоего гуру подсмотренным, рецептом. Панацеи не существует)
35. triviumfan 92 10.03.20 15:52 Сейчас в теме
(31) Значит другие способы были просто неоптимальны :)
36. KilloN 56 01.10.20 10:10 Сейчас в теме
Буквально сегодня столкнулся с одной задачей в отчете:

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


Очень спорное утверждение! Любой инструмент важно применять там где это более оптимально, а не "везде пихаю единый запрос".
Из-за такого программера полностью отсчет переписываю, оказывается при едином запросе не работает расшифровка до регистратора, и она вообще не предусмотрена была =)

По поводу примера оптимизации. Мне нужно получить последние даты продажи и закупа, как я получал эти данные сначала одним запросом а, затем запросом в цикле, и запрос в цикле выдал в 60 раз быстрее.

НАПРИМЕР:

Есть не важно какая конфигурация, Необходимо на каждую строку списка товаров получить последние данные о движении товара, как это сделать оптимальнее?

Вопрос состоит в том, что если использовать СписокНоменклатуры в связях СКД то в запросе нужно получить все данные из таблицы и затем отобрать по последней дате. Запрос Формируется 63 сек, если использовать запрос в цикле 1.

Итого Данные запроса без цикла формата
ВЫБРАТЬ
	МАКСИМУМ(Таблица.Период) КАК Период,
	Таблица.Номенклатура КАК Номенклатура
ИЗ
	РегистрНакопления.Таблица КАК Таблица
ГДЕ
	Таблица.Номенклатура В(&Номенклатура)

СГРУППИРОВАТЬ ПО
	Таблица.Номенклатура
Показать


63 274 мс (63 сек)

Запрос в цикле Формата:
ВЫБРАТЬ ПЕРВЫЕ 1
	МАКСИМУМ(Таблица.Период) КАК Период,
	Таблица.Номенклатура КАК Номенклатура
ИЗ
	РегистрНакопления.Таблица КАК Таблица
ГДЕ
	Таблица.Номенклатура = &Номенклатура

СГРУППИРОВАТЬ ПО
	Таблица.Номенклатура
Показать


1 326 мс (1 сек)
37. nomad_irk 71 01.10.20 10:24 Сейчас в теме
(36)Т.е. запросом вы сразу всю номенклатуру проверили за 63 секунды, а одна итерация цикла выполнялась за 1.3 секунды? или весь цикл выполнился за 1.3 секунды?
38. FatPanzer 01.10.20 10:36 Сейчас в теме
(37) Я тоже в сказки не верю.
39. KilloN 56 01.10.20 10:39 Сейчас в теме
(37)
у проверили за 63 секунды, а одна итерация цикла выполнялась за 1.3 секунды? или весь цикл выполнился за 1.3 с


Наверное не корректно выразился, весь результат Макета компоновки данных формировался 63 секунды при поиске последних дат 1 запросом, а тажа самая схема с измененным набором и связью 1.3 сек:

По простому весь цикл выполнился за 1.3 секунды

Компоновка макета в ГенераторМакетаКомпоновкиДанных - 447 мс
Формирование результата - 1 342 мс


В скрине менялась только таблица в красной рамочке.
Прикрепленные файлы:
40. nomad_irk 71 01.10.20 10:58 Сейчас в теме
(39) А можно замер производительности для случая "как было" и "как стало"?
Сортировать лучше по номеру строки в модуле, чтобы было понятно, как происходит выполнение кода.
41. KilloN 56 01.10.20 11:19 Сейчас в теме
(40)
(39) А можно замер производительности для случая "как было" и "как стало"?
Сортировать лучше по номеру строки в модуле, чтобы было понятно, как происходит выполнение кода.


Не пойму вопроса, какая из 6 строчек интересует?

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки, ДанныеРасшифровки);

Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.Вывести(Процессор)
Показать


Компоновка макета в ГенераторМакетаКомпоновкиДанных - 442 мс
Формирование результата - 75 522 мс
Компоновка макета в ГенераторМакетаКомпоновкиДанных - 433 мс
Формирование результата - 1 351 мс
42. nomad_irk 71 01.10.20 11:34 Сейчас в теме
(41)
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки, ДанныеРасшифровки);

при цикличном выполнении так же должно выполнятся в цикле, не? параметр Номенклатура внутри Настройки меняется, не?
43. KilloN 56 01.10.20 11:42 Сейчас в теме
(42)
при цикличном выполнении так же должно выполнятся в цикле, не? параметр Номенклатура внутри Настройки меняется, не?


Конечно же нет, запрос в цикле на уровне СКД через связи наборов данных, а не на уровне кода.=)
Прикрепленные файлы:
44. FatPanzer 01.10.20 11:45 Сейчас в теме
(43) Так это не запрос в цикле.
46. KilloN 56 01.10.20 12:07 Сейчас в теме
(44)
Так это не запрос в цикле.


А что это по твоему?

На каждую строчку одной таблицы, в цикле подставляются разные параметры. Как же это назвать?
48. FatPanzer 01.10.20 12:11 Сейчас в теме
(46) Я могу это назвать как угодно - динамическим формированием запроса в виде множества объединений и так далее. Но по итогам всего этого фактический запрос на выполнение из 1С к СУБД происходит один.
А запросом в цикле называется сситуация, когда тупо в цикле несколько раз запрос ВЫПОЛНЯЕТСЯ, то есть цикличное обращение из 1С к самой СУБД.
49. KilloN 56 01.10.20 12:20 Сейчас в теме
(48)
запросом в цикле называется сситуация, когда тупо в цикле несколько раз запрос ВЫПОЛНЯЕТСЯ, то есть цикличное обращение к самой СУБД.


Кто тебе такое сказал?))
Цикличное обращение к СУБД - это одно, а запрос в цикле это другое.
Коррелированные запросы - это тоже запрос в цикле, хотя по факту может быть одно обращение к БД.

Кто вообще привязал запросы в цикле к обращению к БД??
50. FatPanzer 01.10.20 12:23 Сейчас в теме
(49) 1С и привязало. Время на построение плана запроса в цикле, время на открытие-закрытие транзакции чтения, время на компилицую самого запроса из 1С в язык SQL... Вот это мы называем затратами на запрос в цикле на встроенном языке.
Если ты не в курсе.
53. KilloN 56 01.10.20 12:43 Сейчас в теме
(50)
1С и привязало.


Не скинешь ссылку на статью от 1с, очень интересно почитать про это =))
45. nomad_irk 71 01.10.20 11:45 Сейчас в теме
(43)При цикличном выполнении номенклатура меняется в параметре, все наборы будут содержать одну запись с указаной в параметре номенклатурой, не?

Или вы там уже пол БД выгребли во временные таблицы и только, грубо говоря, выполняете по ним поиск записей с нужной вам номенклатурой?
47. KilloN 56 01.10.20 12:11 Сейчас в теме
(45)
(43)Так при цикличном выполнении номенклатура меняется в параметре, все наборы будут содержать одну запись с указаной в параметре номенклатурой, не?


Чувак ты вообще работал с СКД? Какая еще одна запись?

1,5 тысяч строк в таблице объединение, значит 1,5 тысячи запросов в цикле с разными параметрами к набору данных ДатыДокументов" типа запрос.
51. nomad_irk 71 01.10.20 12:31 Сейчас в теме
(47)Твои 1.5тысячи строк уже в ОЗУ, найти в них 1.5 тысячи раз уникальную номенклатуру - много ресурсов не нужно.
Чувак, ты вообще в курсе, что называется запросом в цикле?

Запрос в цикле это когда результат запроса к БД возвращает данные только для указанных параметров запроса.
Изменились параметры запроса - запрашиваются новые данные из БД.
54. KilloN 56 01.10.20 12:57 Сейчас в теме
(51)
Чувак, ты вообще в курсе, что называется запросом в цикле?


Ответь для себя для начала что такое "Запрос" и что такое "Цикл"?

(51)
Запрос в цикле это когда результат запроса возвращает данные только для указанных параметров запроса.
Изменились параметры запроса - запрашиваются новые данные из БД.


Все правильно, "результат запроса возвращает данные только для указанных параметров запроса", на каждую строчку одного запроса запрашиваются данные в БД из другого 1,5 тысячи раз в ЦИКЛЕ.
Также формируются коррелированные запросы, в которых которых "результат запроса возвращает данные только для указанных параметров запроса" в ЦИКЛЕ.
Не даром коррелированные запросы называются ЗАПРОСАМИ, а не как то по другому.
52. SlavaKron 01.10.20 12:33 Сейчас в теме
(43) "Параметры" очищали при проверке варианта "одним запросом"?
55. KilloN 56 01.10.20 12:58 Сейчас в теме
(52)
"Параметры" очищали при проверке варианта "одним запросом"?


Каким образом? Этим СКД управляет
56. пользователь 26.09.23 09:31
Сообщение было скрыто модератором.
...
Оставьте свое сообщение