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

20.12.23

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

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

Скачать файл

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

Наименование По подписке [?] Купить один файл
Производительность: особенности применения таблиц значений при работе с выборками данных:
.epf 9,09Kb
0
0 Скачать (1 SM) Купить за 1 850 руб.

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

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

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

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С v8.3 Бесплатно (free)

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

06.06.2024    9255    Evg-Lylyk    61    

44

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

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

13.03.2024    5094    spyke    28    

49

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    7571    vasilev2015    20    

42

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

2 стартмани

15.02.2024    12416    241    ZAOSTG    80    

115

HighLoad оптимизация Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Принимать, хранить и анализировать показания счетчиков (метрики) в базе 1С? Почему бы нет? Но это решение быстро привело к проблемам с производительностью при попытках построить какую-то более-менее сложную аналитику. Переход на PostgresSQL только временно решил проблему, т.к. количество записей уже исчислялось десятками миллионов и что-то сложное вычислить на таких объемах за разумное время становилось все сложнее. Кое-что уже практически невозможно. А что будет с производительностью через пару лет - представить страшно. Надо что-то предпринимать! В этой статье поделюсь своим первым опытом применения СУБД Clickhouse от Яндекс. Как работает, что может, как на нее планирую (если планирую) переходить, сравнение скорости работы, оценка производительности через пару лет, пример работы из 1С. Все это приправлено текстами запросов, кодом, алгоритмами выполненных действий и преподнесено вам для ознакомления в этой статье.

1 стартмани

24.01.2024    5668    glassman    18    

40

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    14008    doom2good    49    

71
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. PowerBoy 3416 20.12.23 10:09 Сейчас в теме
Правильней было бы какое то значение из выборки и тз все таки считывать.
7. PowerBoy 3416 20.12.23 13:53 Сейчас в теме
(1) Оставьте только одно поле в запросе, повторите тест, сравните.
12. evgen7938 14 21.12.23 08:09 Сейчас в теме
(7) да, наверное, есть смысл. Возможно, стоит в таблицу значений добавить еще и индекс и сравнить разницу с учетом индексации таблицы.
2. RocKeR_13 1366 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 3087 20.12.23 10:34 Сейчас в теме
(2)
при большой выборке
Хороший нюанс. Когда Вы обрабатывали действительно большую выборку в последний раз? Если с Вами такое случается регулярно, то у Вас проблемы с архитектурой.
5. RocKeR_13 1366 20.12.23 10:56 Сейчас в теме
(4) обычно большие объемы встречаются при различных интеграциях и обменах, когда нужно первоначально выгрузить большое количество данных. Есть импортеры с большими закупками маркируемых товаров или производители с той же маркировкой: в той или иной задаче опять же иногда приходится получать ощутимую выборку по товарам совместно с кодами маркировки.

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

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

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

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

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