История одной оптимизации, давшей тысячекратный прирост производительности!

09.02.26

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

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

Эта история началась поставленной мне задачи переноса доработок функционала в документа Сверка взаиморасчетов 2.4 в документ Сверка взаиморасчетов 2.5.

Когда я увидел существующий код, мне сразу стало очевидно, что это вопиющие расточительство вычислительных ресурсов!

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

Существующий код выполнился за 2006 секунд




Оптимизированный код выполнился за 2 секунды




Фантастика! Рост производительности в тысячу раз!

Ниже представлен существующий код:

&НаКлиенте
&После("ЗаполнитьПоОстаткамЗавершение")
Процедура ИНФ_ЗаполнитьПоОстаткамЗавершение(Результат, ДополнительныеПараметры) Экспорт

	ИНФ_ЗаполнитьПоОстаткамПосле(ЭтаФорма.Команды.ЗаполнитьПоОстаткам);

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

&НаКлиенте
Процедура ИНФ_ЗаполнитьПоОстаткамПосле(Команда)

	Для каждого Строка из Объект.ДетальныеЗаписиРасчеты Цикл
		Если  ТипЗНЧ(Строка.РасчетныйДокумент) = Тип("ДокументСсылка.ОтчетКомитенту") Тогда
			ВыбранноеЗначение = Строка.РасчетныйДокумент;
			НомерИМ = ПоискНомераЗаказаИМ(ВыбранноеЗначение);
			Если ЗначениеЗаполнено(НомерИМ) Тогда
				Строка.ОписаниеДокумента = "Заказ № " + НомерИМ.РезультатНомер + " от "+НомерИМ.РезультатДата;
			КонецЕсли;
		ИначеЕсли ТипЗНЧ(Строка.РасчетныйДокумент) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
			Строка.ОписаниеДокумента = Строка.ОписаниеДокумента + " (" + Строка(Строка.РасчетныйДокумент) + ")";
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

Функция ПоискНомераЗаказаИМ(ВыбранноеЗначение)
	ЗапросНомер = Новый Запрос;
	ЗапросНомер.УстановитьПараметр("Ссылка", ВыбранноеЗначение);
	ЗапросНомер.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9"));

	ЗапросНомер.Текст = "ВЫБРАТЬ
		|	ОтчетКомитентуДополнительныеРеквизиты.Значение КАК Значение
		|ИЗ
		|	Документ.ОтчетКомитенту.ДополнительныеРеквизиты КАК ОтчетКомитентуДополнительныеРеквизиты
		|ГДЕ
		|	ОтчетКомитентуДополнительныеРеквизиты.Ссылка = &Ссылка
		|	И ОтчетКомитентуДополнительныеРеквизиты.Свойство = &Свойство
		|";
	Выборка = ЗапросНомер.Выполнить().Выбрать();

	Пока Выборка.Следующий() Цикл
	    РезультатНомер = Выборка.Значение;
	КонецЦикла;

	ЗапросДата = Новый Запрос;
	ЗапросДата.УстановитьПараметр("Значение", РезультатНомер);
	ЗапросДата.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9"));

	ЗапросДата.Текст = "ВЫБРАТЬ
		|	ЗаказКлиентаДополнительныеРеквизиты.Значение КАК Значение,
		|	ЗаказКлиентаДополнительныеРеквизиты.Ссылка.Дата КАК Дата
		|ИЗ
		|	Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДополнительныеРеквизиты
		|ГДЕ
		|	ЗаказКлиентаДополнительныеРеквизиты.Свойство = &Свойство
		|	И ЗаказКлиентаДополнительныеРеквизиты.Значение = &Значение
		|";
	ВыборкаДата = ЗапросДата.Выполнить().Выбрать();

	Пока ВыборкаДата.Следующий() Цикл
	    РезультатДата = ВыборкаДата.Дата;
	КонецЦикла;

	РезультатНомер = СтрЗаменить(СокрЛ(СтрЗаменить(РезультатНомер,"0"," "))," ","0");
	РезультатДата = Формат(РезультатДата,"ДФ=dd.MM.yyyy");

	СтруктураТекст = Новый Структура;
	СтруктураТекст.Вставить("РезультатНомер",РезультатНомер);
    СтруктураТекст.Вставить("РезультатДата",РезультатДата);

	Возврат ?(СтруктураТекст=Неопределено,0,СтруктураТекст);
КонецФункции


Разберём недостатки этого кода:

Первый источник потерь  в процедуре "ИНФ_ЗаполнитьПоОстаткамПосле" реализован обход табличной части на клиенте с вызовом внутри тела цикла функции "ПоискНомераЗаказаИМ", выполняющейся на сервере.

Обращаю внимание, что перед объявлением функции "ПоискНомераЗаказаИМ" отсутствует какой-либо модификатор, это значит, что по умолчанию на сервер будет передаваться полный контекст формы.

При этом платформа 1С:

  • на стороне клиента, сериализует объект формы (со всеми реквизитами формы и объекта включая табличные части)
  • сериализованные данные передаются на сервер
  • на сервере, сериализованные данные десереализуются в объект формы
  • на сервере выполнятся вызванная функция 
  • сервер сериализует объект формы и возвращает его вместе с результатом функции на клиент
  • на стороне клиента, сериализованные данные десереализуются в объект формы

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

Второй источник потерь сама функция "ПоискНомераЗаказаИМ" в ней выполняются аж 4 запроса:

Два явных запроса и два неявных, выполняющих поиск ссылки на дополнительный реквизит, при передаче параметров явным запросам:

ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9")


Дополнительный реквизит можно было получить один раз перед телом цикла, поместить в переменную и далее использовать сохранённое в переменной значение.

Основные направления оптимизации - это сократить количество обращений к серверу и базе данных до минимума. Чтобы ускорить работу, нужно перенести обход табличной части на сервер и вместо получения информации из базы по каждой строке табличной части, получить данные пакетом сразу для всех строк таблицы, которые подлежат обработке.

Согласно концепции, изложенной выше, получился следующий оптимизированный код:

&НаКлиенте
&После("ЗаполнитьПоОстаткамЗавершение")
Процедура ИНФ_ЗаполнитьПоОстаткамЗавершение(Результат, ДополнительныеПараметры) Экспорт

	ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам();

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

&НаСервере
Процедура ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам()

	Перем 	тзИсходныеДанные, КЧ, МассивТипов, сеДопустимыеТипы,
			Элем, Инд, КодТипа, ВГраница, Стр, НСтр, Свойство_НомерЗаказаIM,
			Запрос, РезультатЗапроса, Выборка1, Выборка2,
			НомерЗаказаIM, Инд_Пред;

	// НомерЗаказаIM
	Свойство_НомерЗаказаIM = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПолучитьСсылку(
			Новый УникальныйИдентификатор("8367e4de-3643-11ec-91f0-005056b343de")
		);

	КЧ = Новый КвалификаторыЧисла(10, 0);


	сеДопустимыеТипы = Новый Соответствие();

	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.ОтчетКомитенту"), 1);
	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.РеализацияТоваровУслуг"), 2);

	МассивТипов = Новый Массив();

	Для Каждого Элем Из сеДопустимыеТипы Цикл
		МассивТипов.Добавить(Элем.Ключ);
	КонецЦикла;

	тзИсходныеДанные = Новый ТаблицаЗначений();
	тзИсходныеДанные.Колонки.Добавить("Инд", Новый ОписаниеТипов("Число",,, КЧ));
	тзИсходныеДанные.Колонки.Добавить("РасчетныйДокумент", Новый ОписаниеТипов(МассивТипов));
	тзИсходныеДанные.Колонки.Добавить("КодТипа", Новый ОписаниеТипов("Число",,, КЧ));

	ВГраница = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты.Количество() - 1;

	Для Инд = 0 По ВГраница Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Инд];

		КодТипа = сеДопустимыеТипы.Получить(ТипЗнч(Стр.РасчетныйДокумент));

		Если КодТипа = Неопределено Тогда
			Продолжить;
		КонецЕсли;

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

	Запрос = Новый Запрос();
	Запрос.Текст =
"//0////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|   т.РасчетныйДокумент,
|	т.КодТипа
|
|		ПОМЕСТИТЬ втИсходныеДанные
|
|ИЗ &тзИсходныеДанные КАК т
|
|ИНДЕКСИРОВАТЬ ПО
|	т.КодТипа
|
|;
|//1////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|	ОтчетКомитентуДР.Значение КАК НомерЗаказаIM,
|   ЕСТЬNULL(ЗаказКлиента.Дата, ДАТАВРЕМЯ(1,1,1)) КАК ДатаЗаказа
|
|ИЗ втИсходныеДанные КАК т
|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтчетКомитенту.ДополнительныеРеквизиты КАК ОтчетКомитентуДР ПО
|			ОтчетКомитентуДР.Ссылка = т.РасчетныйДокумент
|		И	ОтчетКомитентуДР.Свойство = &Свойство_НомерЗаказаIM
|
|	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДР ПО
|			ЗаказКлиентаДР.Свойство = &Свойство_НомерЗаказаIM
|		И	ЗаказКлиентаДР.Значение = ОтчетКомитентуДР.Значение
|
|	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента ПО
|			НЕ ЗаказКлиентаДР.Ссылка ЕСТЬ NULL
|		И	ЗаказКлиента.Ссылка = ЗаказКлиентаДР.Ссылка
|
|ГДЕ
|		т.КодТипа = 1	// ОтчетКомитенту
|
|УПОРЯДОЧИТЬ ПО
|	т.Инд,
|	ЕСТЬNULL(ЗаказКлиента.Проведен, Ложь) УБЫВ,
|	ЕСТЬNULL(ЗаказКлиента.ПометкаУдаления, Ложь)
|;
|//2////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(т.РасчетныйДокумент КАК Документ.РеализацияТоваровУслуг)) КАК ПредставлениеДокумента
|
|ИЗ втИсходныеДанные КАК т
|ГДЕ
|		т.КодТипа = 2	// РеализацияТоваровУслуг
|";
	Запрос.УстановитьПараметр("тзИсходныеДанные", тзИсходныеДанные);
	Запрос.УстановитьПараметр("Свойство_НомерЗаказаIM", Свойство_НомерЗаказаIM);

	РезультатЗапроса = Запрос.ВыполнитьПакет();


	// ОтчетКомитенту

	Выборка1 = РезультатЗапроса[1].Выбрать();

	Пока Выборка1.Следующий() Цикл

		Если Выборка1.Инд = Инд_Пред Тогда
			Продолжить;
		КонецЕсли;

		Инд_Пред = Выборка1.Инд;

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка1.Инд];

		НомерЗаказаIM = СтрЗаменить(
				СокрЛ(СтрЗаменить(Выборка1.НомерЗаказаIM, "0", " ")),
				" ", "0"
			);

		Стр.ОписаниеДокумента = СтрШаблон(
				"Заказ № %1 от %2",
		        НомерЗаказаIM,
				Формат(Выборка1.ДатаЗаказа, "ДФ=дд.ММ.гггг")
			);
	КонецЦикла;


	// РеализацияТоваровУслуг

	Выборка2 = РезультатЗапроса[2].Выбрать();

	Пока Выборка2.Следующий() Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка2.Инд];

		Стр.ОписаниеДокумента = СтрШаблон(
				"%1 (%2)",
				Стр.ОписаниеДокумента,
				Выборка2.ПредставлениеДокумента
			);

	КонецЦикла;

КонецПроцедуры // ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам


Вкратце пройдусь по применённым техническим решениям:

С клиента управление сразу передаётся на сервер и далее все манипуляции с табличной частью документа происходят на сервере.

Для того чтобы получить одним запросом нужные нам данные (по всем обрабатываемым строкам табличной части) создаётся таблица значений, в которую записывается индекс строки табличной части, ссылка на расчётный документ и числовой код типа, который позволит быстро идентифицировать и индексировать содержимое временной таблицы по типам документов:

	КЧ = Новый КвалификаторыЧисла(10, 0);


	сеДопустимыеТипы = Новый Соответствие();

	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.ОтчетКомитенту"), 1);
	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.РеализацияТоваровУслуг"), 2);

	МассивТипов = Новый Массив();

	Для Каждого Элем Из сеДопустимыеТипы Цикл
		МассивТипов.Добавить(Элем.Ключ);
	КонецЦикла;

	тзИсходныеДанные = Новый ТаблицаЗначений();
	тзИсходныеДанные.Колонки.Добавить("Инд", Новый ОписаниеТипов("Число",,, КЧ));
	тзИсходныеДанные.Колонки.Добавить("РасчетныйДокумент", Новый ОписаниеТипов(МассивТипов));
	тзИсходныеДанные.Колонки.Добавить("КодТипа", Новый ОписаниеТипов("Число",,, КЧ));


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

	ВГраница = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты.Количество() - 1;

	Для Инд = 0 По ВГраница Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Инд];

		КодТипа = сеДопустимыеТипы.Получить(ТипЗнч(Стр.РасчетныйДокумент));

		Если КодТипа = Неопределено Тогда
			Продолжить;
		КонецЕсли;

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


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

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

	Выборка1 = РезультатЗапроса[1].Выбрать();

	Пока Выборка1.Следующий() Цикл

		Если Выборка1.Инд = Инд_Пред Тогда
			Продолжить;
		КонецЕсли;

		Инд_Пред = Выборка1.Инд;

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка1.Инд];

		НомерЗаказаIM = СтрЗаменить(
				СокрЛ(СтрЗаменить(Выборка1.НомерЗаказаIM, "0", " ")),
				" ", "0"
			);

		Стр.ОписаниеДокумента = СтрШаблон(
				"Заказ № %1 от %2",
		        НомерЗаказаIM,
				Формат(Выборка1.ДатаЗаказа, "ДФ=дд.ММ.гггг")
			);
	КонецЦикла;


Код тестировался на платформе 8.3.27.1688, на конфигурации КА 2.5.22.134.

Вступайте в нашу телеграмм-группу Инфостарт

Оптимизация убираем запрос из цикла

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Рефакторинг и качество кода Разработчик 1С 8.3 1С 8.5 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Знакомая последовательность. Внешний отчет на СКД: модуль объекта на две тысячи строк, девять текстов запросов, три набора данных со связями. Переделываю под другую базу, собираю ERF, прогоняю пакетную проверку конфигуратором, чисто. Отдаю. Через двадцать минут приходит скриншот: «Переменная не определена». Правлю, пересобираю, отдаю. Через двадцать минут второй: «Не задано значение параметра». Два круга через живого человека ради двух ошибок, каждая из которых воспроизводится на той же машине за три секунды. Если знать, чем ее воспроизводить. Воспроизводит ее COM-коннектор, и дальше вся статья про то, как из него собрать проверку, которая умеет падать.

28.09.2026    272    KonMa    0    

2

Рефакторинг и качество кода Разработчик 1С 8.3 1С:Управление торговлей 11 Россия Бесплатно (free)

8 приёмов за 10 минут: перестаньте прокручивать общий модуль на три тысячи строк как ленту в соцсети. Outline, #Область и фильтр - и вы уже в нужной процедуре, а не на строке «где-то внизу».

25.09.2026    1521    aleksandrboldyusov    6    

15

Перенос данных 1C Рефакторинг и качество кода Разработчик 1С 8.3 Бесплатно (free)

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

24.09.2026    396    nedomolkov.ivan    0    

0

Рефакторинг и качество кода Обновление 1С Разработчик 1С 8.3 Бесплатно (free)

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

22.09.2026    555    1c-izh    0    

5

Рефакторинг и качество кода Тестирование QA Разработчик Бесплатно (free)

Штатная страховка внутри цепочки обработки умеет прятать дефекты того шага, который стоит перед ней. У нас так и вышло: валидатор чинил результат постфактум, на выходе всё выглядело корректно, и никто не видел, что предыдущий шаг молча теряет данные. Вылезло это только на независимой проверке чужими глазами. Разбираю, чем инвариант отличается от сценарного теста и почему обычное умножение вытащило дефект из красивой метрики 0,997. Отдельно про 13 дублей, которые приехали из источника ещё до всякой обработки, и про две находки, которые оказались вообще не моими: они жили в эталонной реализации, откуда я списывал логику. Вторая часть про лимит выхода модели: почему обрезка ответа по длине это тихий ноль в мониторинге и как смена формата на дельты уронила выход до 4 951 токена. Есть отклонённые гипотезы и честный список того, чего мы так и не померили.

21.09.2026    457    nedomolkov.ivan    2    

1

WEB-интеграция Рефакторинг и качество кода Системный администратор Разработчик 1С 8.3 Бесплатно (free)

Я сел проверять внутренний поисковый сервис по коду: можно ли доверять ему в автоматическом режиме. Сверка с обычным текстовым поиском по файлам дала 261 из 261, 264 из 264 и 182 из 182 совпадений, разбор структуры файла - 318 функций из 318. Стопроцентная точность. Этот же замер и вскрыл, что опираться на сервис нельзя: искал он безупречно, только совсем не в том месте, которое я ему называл. Внутри разбор трёх дефектов, сложившихся в один тихий отказ: аргумент, проглоченный без ошибки; умолчание, выставленное когда-то наугад; снимок данных, у которого в ответе не указан возраст. Плюс регулярное задание, которое вся команда считала работающим и которого не существовало никогда. Перенос на 1С прилагается: готовый цикл проверки, после которого HTTP-сервис перестаёт молча принимать мусор.

21.09.2026    460    nedomolkov.ivan    0    

0

Логистика, склад и ТМЦ Рефакторинг и качество кода Разработчик Аналитик Руководитель проекта 1С 8.3 Бесплатно (free)

Кладовщик получает задачу: на складе проверки лежат две штуки. Идёт в зону, а там всё на месте и никакой задачи в складской системе нет. Так работала автоматическая сверка остатков между учётной и складской системами: разницу она переносила документом, а комментарий к этому документу восемь месяцев отправлял людей искать несуществующий ноль. Робота разобрали до кода. Обе сравниваемые величины оказались синтетическими: слева физический срез с вычетами по активности и окнами в 60 минут и 12 часов, справа учётный остаток на конец дня минус трёхчасовой хвост непроведённых ордеров. Порог срабатывания стоял в нуле, поэтому робот исправно оформлял собственный шум измерения: за 60 дней он сам создал 62,7% оборота технического склада, а 2 081 артикул из 2 102 приезжал туда и уезжал обратно. Внутри обе формулы, замер лага отгрузки, снятая гипотеза и честная граница данных.

21.09.2026    471    nedomolkov.ivan    2    

0
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user-z99999 78 09.02.26 14:40 Сейчас в теме
А учтена ситуация, когда в документ в табличную часть добавляется новая строка?
как там данные будут получены.

Вообще, если хотите сильно уменьшить, попробуйте вообще не считать на сервере,
если логика работы позволяет.
Только при нажатии на кнопку, один раз бежим на сервер и всё приносим. Пользователь сам определяет когда.
Чтобы для черновика не бегать.
2. paulwist 09.02.26 14:42 Сейчас в теме
ИНДЕКСИРОВАТЬ ПО
| т.КодТипа


1. Сколько записей в ВТ с КодТипа =1 и КодТипа =2 ??

2. Объясните, зачем индексируете по т.КодТипа, какой результат хотите получить?
9. Eugen-S 453 14.02.26 15:29 Сейчас в теме
(2) В теории отбор по индексированному полю работает быстрее, чем по неиндексированному.
В последующих запросах идёт отбор как раз по этому полю, поэтому я применил индексацию.
Обратная сторона индексации, что при наличии индексации на запись строки таблицы расходуется чуть больше времени.

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

Поэтому я решил, что лучше её сделать, чем не сделать.
VyacheslavShilov; +1 – Ответить
10. paulwist 16.02.26 08:51 Сейчас в теме
(9)
В последующих запросах идёт отбор как раз по этому полю, поэтому я применил индексацию.


Хмм, в запросах вижу, что отбор идёт по предикату КодТипа =1 и КодТипа =2, кстати по которому нет индекса (о его необходимости говорит ответ на вопрос 1. Сколько записей в ВТ с КодТипа =1 и КодТипа =2 ??
) и не вижу отбор по т.Инд.


(9)
А в общем, Ваш вопрос напоминает расхожий в интернете комикс-притчу, про отца, сына и их осла.
Если бы я не сделал индексацию, обязательно в комментариях появился бы тот, кто спросил бы почему я её не сделал.


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

Можете привести план запросов??
3. sapervodichka 7628 09.02.26 15:15 Сейчас в теме
Вообще я не склонен ругать разработчика за первоначальный неоптимальный код. Сначала ведь надо в принципе написать какое-то рабочее решение (там и с ТЗ могут быть проблемы - непонятно что в итоге сделать, поэтому делают максимально просто и с возможностью быстро поправить, и делать могут в демке на 1-5 записях где проблема не видна). А вот далее на реальных данных можно и нужно решение оптимизировать, но вот только на оптимизацию чаше всего времени или денег не дают, что очень жаль. А она нужна.
Автору, чашечка уважения. Приятно читать задачи по оптимизации и складывать себе на подкорку.
SemandCheb; +1 – Ответить
4. paulwist 10.02.26 08:26 Сейчас в теме
(3)
А вот далее на реальных данных можно и нужно решение оптимизировать,


Дык у ТСа "реальные" данные - 2006 сек запрос отрабатывал, если принять "пальцем в небо" что 2 сек обрабатывается одна запись, то получается 1000 записей.

Что фактически сделал ТС, он "заменил" 1000 транзакций на одну и получил ожидаемое ускорение.
5. sapervodichka 7628 10.02.26 08:33 Сейчас в теме
(4) я писал о том, что написание кода по ТЗ и его оптимизация - это две разные задачи, которые делают разные люди в разное время. То что там 2006, 1000, ускорение и т.д. я прочитал не слепой
6. paulwist 10.02.26 10:19 Сейчас в теме
(5)
я писал о том, что написание кода по ТЗ и его оптимизация - это две разные задачи


Тут возражений нет :) +100500
sapervodichka; +1 – Ответить
7. starik-2005 3303 10.02.26 10:43 Сейчас в теме
Лет шесть назад оптимизировал загрузку недействительных паспортов. Начальное время вставки в таблицу из двух полей с индексами в 1С было 8 часов, итого на С формирование битовой маски работало за полторы минуты (из них 95% времени - это распаковка 1G+ gz-файла). Т.е. в 320 раз, если с временем распаковки. Если же считать только время загрузки, то в стопиццот раз.
VyacheslavShilov; +1 – Ответить
8. axelerleo 325 13.02.26 23:50 Сейчас в теме
Хороший пример своевременной оптимизации. Как правило, практически любая разработка проходит стадии от "сделай хоть как-то" до "сделай чтоб быстро". Богачев говорит, что преждевременная оптимизация не имеет особого смысла, и омтимизировать надо то, что реально тормозит, и тогда, когда реально тормозит. А для выявления этого есть нагрузочные тесты. Вот тогда то весь код и всплывает :)
Eugen-S; VyacheslavShilov; +2 – Ответить
Для отправки сообщения требуется регистрация/авторизация