Производительность: особенности применения таблиц значений при работе с выборками данных

20.12.23

База данных - HighLoad оптимизация

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

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Производительность: особенности применения таблиц значений при работе с выборками данных:
.epf 9,09Kb
0 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

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

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

Коллеги, здравствуйте!

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

Чем руководствовался:

1. Обработка больших объемов данных занимает много времени;

2. Создание дополнительных объектов (речь про таблицу значений) - это накладные расходы, что влияет на производительность (в худшую сторону);

3. "Да, таблица значений - это зло, но это удобно и хочется понимать, сколько это стоит".

 

Начнем

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

Вот формирование запроса:

Функция ПолучитьЗапрос() 
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	               |	Продажи.Период,
	               |	Продажи.Регистратор,
	               |	Продажи.НомерСтроки,
	               |	Продажи.Активность,
	               |	Продажи.Номенклатура,
	               |	Продажи.ХарактеристикаНоменклатуры,
	               |	Продажи.ЗаказПокупателя,
	               |	Продажи.ДоговорКонтрагента,
	               |	Продажи.ДокументПродажи,
	               |	Продажи.Подразделение,
	               |	Продажи.Проект,
	               |	Продажи.Организация,
	               |	Продажи.Контрагент,
	               |	Продажи.Акция,
	               |	Продажи.Количество,
	               |	Продажи.Стоимость,
	               |	Продажи.СтоимостьБезСкидок,
	               |	Продажи.НДС
	               |ИЗ
	               |	РегистрНакопления.Продажи КАК Продажи
	               |ГДЕ
	               |	Продажи.Период >= &ДатаНачала
	               |	И Продажи.Период <= &ДатаОкончания";
	Возврат Запрос;
	
КонецФункции

 

Условно выбираем период и делаем нарезки:

  1. сначала выбираем данные за первый день из периода;
  2. потом за 2 первых дня;
  3. потом за 3 первых дня; 
  4. ...
  5. потом за весь период

 

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

ДатаОкончания = Период.ДатаОкончания;
ТекущаяДатаОкончания = КонецДня(Период.ДатаНачала);
Запрос = ПолучитьЗапрос();
Запрос.УстановитьПараметр("ДатаНачала", Период.ДатаНачала);

	
Пока ТекущаяДатаОкончания <= Период.ДатаОкончания Цикл
		
		Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДатаОкончания);
		
		РезультатЗапроса = Запрос.выполнить();
		стр = Замеры.Добавить();
		_Итоги_ДанныеВыборкой = ОбработатьДанныеВыборкой(РезультатЗапроса);
		_Итоги_ДанныеТЗ = ОбработатьДанныеТЗ(РезультатЗапроса);
		стр.КоличествоЗаписей = _Итоги_ДанныеВыборкой.КоличествоЗаписей;
		стр.ВремяДляВыборки = _Итоги_ДанныеВыборкой.Время;
		стр.ВремяДляТЗ = _Итоги_ДанныеТЗ.Время;
		стр.Коэффициент = стр.ВремяДляТЗ/стр.ВремяДляВыборки;
		
		
		ТекущаяДатаОкончания = КонецДня(ТекущаяДатаОкончания + 60*60*24);
КонецЦикла;

 

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

Функция ОбработатьДанныеВыборкой(Результат) 
	
	КоличествоЗаписей = 0;
	Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
	Выборка = Результат.Выбрать();
	Пока выборка.следующий() Цикл
		
		КоличествоЗаписей = КоличествоЗаписей + 1;
	КонецЦикла;
	Конец = ТекущаяУниверсальнаяДатаВМиллисекундах();
	
	Возврат Новый структура("Время, КоличествоЗаписей", Конец-Начало, КоличествоЗаписей);
	
КонецФункции

Функция ОбработатьДанныеТЗ(Результат) 
	
	КоличествоЗаписей = 0;
	Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
	тз = Результат.Выгрузить();
	для каждого стр из тз Цикл
		
		КоличествоЗаписей = КоличествоЗаписей + 1;
	КонецЦикла;
	Конец = ТекущаяУниверсальнаяДатаВМиллисекундах();
	
	Возврат Новый структура("Время, КоличествоЗаписей", Конец-Начало, КоличествоЗаписей);
	
КонецФункции

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

_Итоги_ДанныеВыборкой = ОбработатьДанныеВыборкой(РезультатЗапроса);
_Итоги_ДанныеТЗ = ОбработатьДанныеТЗ(РезультатЗапроса);

стр.КоличествоЗаписей = _Итоги_ДанныеВыборкой.КоличествоЗаписей;
стр.ВремяДляВыборки = _Итоги_ДанныеВыборкой.Время;
стр.ВремяДляТЗ = _Итоги_ДанныеТЗ.Время;
стр.Коэффициент = стр.ВремяДляТЗ/стр.ВремяДляВыборки;

 

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

 

Результат 1

 

Результат 2

 

Вывод

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

Тестировал на платформе 1С:Предприятие 8.3 (8.3.13.1644) в режиме совместимости с 8.2.13.

Проверено на следующих конфигурациях и релизах:

  • Управление торговлей, редакция 10.3, релизы 10.3.45.4

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

См. также

HighLoad оптимизация Программист 1С 8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    10797    ivanov660    48    

53

HighLoad оптимизация Программист 1С:Предприятие 8 1C:ERP Бесплатно (free)

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

18.02.2025    12184    ivanov660    39    

62

HighLoad оптимизация Программист Россия Бесплатно (free)

А вы знали, что сервер 1С при соединении с базой на сервере PostgreSQL самостоятельно устанавливает некоторые параметры? Это важно знать при настройке сервера и отладке долгих запросов. Предлагаю разобраться.

27.08.2024    7021    soulner    10    

40

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    14892    ivanov660    13    

64

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    21347    Evg-Lylyk    73    

46

HighLoad оптимизация Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    11165    spyke    29    

54
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. PowerBoy 3501 20.12.23 10:09 Сейчас в теме
Правильней было бы какое то значение из выборки и тз все таки считывать.
7. PowerBoy 3501 20.12.23 13:53 Сейчас в теме
(1) Оставьте только одно поле в запросе, повторите тест, сравните.
12. evgen7938 33 21.12.23 08:09 Сейчас в теме
(7) да, наверное, есть смысл. Возможно, стоит в таблицу значений добавить еще и индекс и сравнить разницу с учетом индексации таблицы.
2. RocKeR_13 1480 20.12.23 10:29 Сейчас в теме
Экзамен "1С:Специалист" по платформе "1С:Предприятие 8"
http://static.1c.ru/rus/partners/training/files/ATT83PL.rtf

Цитата из раздела с описаниями ошибок:

Выгрузка результата запроса в промежуточную таблицу (например, в таблицу значений) без необходимости - минус 1 балл


Здесь основная проблема заключается даже не столько в производительности, сколько в том, что выгрузка результата запроса сразу помещается в оперативную память. Особенно это чувствуется при использовании 32-битной платформы: при большой выборке данных работа просто будет прекращена из-за нехватки памяти. А вот при использовании выборки в случае превышения размера имеющейся памяти данные будут размещены во временных файлах и будут считываться при вызовах метода обхода выборки Следующий()

Источник: 1С:Предприятие 8. Система стандартов и методик разработки конфигураций
SagittariusA; ixijixi; +2 Ответить
4. starik-2005 3294 20.12.23 10:34 Сейчас в теме
(2)
при большой выборке
Хороший нюанс. Когда Вы обрабатывали действительно большую выборку в последний раз? Если с Вами такое случается регулярно, то у Вас проблемы с архитектурой.
5. RocKeR_13 1480 20.12.23 10:56 Сейчас в теме
(4) обычно большие объемы встречаются при различных интеграциях и обменах, когда нужно первоначально выгрузить большое количество данных. Есть импортеры с большими закупками маркируемых товаров или производители с той же маркировкой: в той или иной задаче опять же иногда приходится получать ощутимую выборку по товарам совместно с кодами маркировки.

Тем не менее, даже в рутинной работе все равно использую выборку из результата запроса. Сейчас даже не вспомню случая, когда нужно было прям вот в таблицу/дерево значений что-то выгружать.
3. starik-2005 3294 20.12.23 10:33 Сейчас в теме
Отличная статья! Но есть и нюансы. Например, получить значение из колонки таблицы значений примерно на 10% быстрее, чем из выборки. По крайней мере на моих данных. Несколько раз тестировал. Но если Вы таким образом считаете количество строк в запросе, то через выборку действительно быстрее.
Andrey_Timofeev; PowerBoy; +2 Ответить
9. evgen7938 33 21.12.23 07:53 Сейчас в теме
(3) Можно еще использовать индексацию - это если данные приходится дергать хаотично, тогда быстрота индексов перевешивает замедление при создании таблицы, но это не точно )

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

Какие преимущества дает этот объект и какие приемы можно использовать - мы пока не рассматриваем, просто, фиксируем факт.
6. ixijixi 2158 20.12.23 11:32 Сейчас в теме
таблица значений - это зло, но это удобно
На самом деле выборка не менее удобна, просто ТЗ визуально можно представить как цельный объект. Если абстрагироваться и представлять выборку в виде объекта, то и неудобства уйдут. По крайней мере, мне помогло.
11. evgen7938 33 21.12.23 08:05 Сейчас в теме
(6) в плане абстракции - да, можно попробовать. Здесь, углом встает вопрос индексирования некоторого объема данных.

Что если требуется быстро обработать набор данных не на стороне СУБД, а именно на сервере/клиенте? Что порекомендуете?
13. ixijixi 2158 21.12.23 08:39 Сейчас в теме
(11) Так от ситуации зависит: что за набор, что понимать под обработкой.
8. Xershi 1558 21.12.23 00:35 Сейчас в теме
Пару лет назад, может 5, видел статью.
Там анализировали обход коллекции через
РезультатЗапроса = Запрос.Выполнить()
И дальше обход результата.
И сразу выполнить и выбрать.
И расписывали какая команда какую даёт нагрузку. На железо.
Попробуйте тоже самое сделать?
10. evgen7938 33 21.12.23 08:00 Сейчас в теме
(8) Думаю, что нет. Наверное, это актуально при перегрузках "железа" большим количеством одновременных вычислительных операций.

У меня на горизонте пока нет таких "горячих" мест, но, конечно, если появятся риски "напороться" на такую особенность, то будем исследовать вопрос.
14. Xershi 1558 21.12.23 12:27 Сейчас в теме
(10) просто у вас такая красивая таблица, было бы здорово посмотреть на разницу.
15. Andrey_Timofeev 14 29.12.23 16:55 Сейчас в теме
У меня при реализации данного алгоритма коэффициент получился около 2. А если еще некоторые вычисления добавить, то разница вполне может получиться не в пользу метода "Выбрать". Реализацию прикрепляю
Прикрепленные файлы:
Тест_СравнениеВыборкиИВыгрузки.zip
16. s22 23 04.01.24 15:33 Сейчас в теме
Это в обычных формах?
Код выполнялся в толстом клиенте?
Для отправки сообщения требуется регистрация/авторизация