Последний раз про срез последних (на каждую дату в запросе)

15.02.21

Разработка - Запросы

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

На проведение данного исследования меня натолкнула статья «Срез на даты за период. Шаблон запроса» с комментариями. Суть статьи: автор привел два варианта решения известной задачи — традиционный и свой собственный («интервальный»). В комментариях оба варианта подверглись резкой критике за сложность — большой объем текста, временные таблицы. Цитирую критиков:

«давно уже подобную задачу решают одним запросом (без всяких временных таблиц) с двумя левыми соединениями»

«Не вникал в смысл задачи, но срез на дату чего-либо по периоду делается простым 1 запросом без всяких ВТ.»

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

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

Оба варианта из комментариев — короткие, лаконичные, но затратные по ресурсам, на мой взгляд.

Но вообще, интересно провести исследование, и цифрами показать, какой из вариантов лучше и на сколько.

Почти год я собирался с мыслями. Потом провел эксперимент. Еще почти год созревал изложить это в виде статьи. Наконец, созрел :)

По ходу изучения темы, мне попался еще один вариант в статье «Минимализмы» п.4. Тоже в один запрос, довольно диковинное решение, вряд ли применимое на практике, но интересное.

Итого получилось 5 вариантов.

На мой взгляд, все такие задачи в реальности примерно одного типа. Возьмем самую типичную:

  • организация продает товары (документ Реализация товаров);
  • их цена хранится в регистре (периодический регистр сведений Цены) и меняется во времени;
  • продавец может устанавливать скидку в момент продажи, но не более некоторого процентного значения;
  • в какой-то момент времени нужно проверить, что все скидки действительно не превышали этого порога;
  • если превышали, то где, когда, на сколько;
  • значения скидок в документах не хранятся (или хранятся, но мы им не доверяем), а считаем отношение цены из документа продажи к значению цены их регистра на дату.
 
Что ж, осталось собрать тестовый стенд и запустить наши запросы:

Железо (ноутбук):

  • процессор AMD Ryzen 5 2500U,
  • оперативная память 12 Gb,
  • диск SSD Samsung PM871b SATA3

Программное обеспечение:

  • Windows 10 Home (64)
  • Microsoft SQL Server 2017 14.0.2002.14 (X64) Developer Edition (64-bit) (для наглядности, я отключил параллельное использование ядер процессора: Max degree of parallelism = 1)
  • 1С:Предприятие 8.3 (8.3.15.1700) (64)

Создаем простую каркасную конфигурацию: «Номенклатура», «Контрагенты», «Продажа товаров», «Цены».

Конфигурация с обработкой инициализации опубликована здесь: github.com/boroda310/slice-slice-slice. В папке configuration — файлы конфигурации.

Инициализируем случайными данными.

1000 товаров:

 
Инициализация 1

Цены на начало периода, случайные переоценки в периоде:

 
Инициализация 2

Продажи в периоде:

 
Инициализация 3

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

Файл для консоли запросов с текстами запросов опубликован здесь: github.com/boroda310/slice-slice-slice в папке requestconsole.

 
Запрос Вариант А (традиционный)
 
Запрос Вариант Б (интервальный)
 
Запрос Вариант В (в один запрос, без группировки)
 
Запрос Вариант Г (в один запрос, с группировкой)
 
Запрос Вариант Д («эшелонный» из ст. «Минимализмы»)

Я запускал все эти запросы за два периода — первый квартал 2020 г. и первое полугодие 2020 г. — на эти периоды генерировались случайные документы и цены. Замерял время выполнения. В ходе анализа планов запросов определился еще один важный показатель — количество обрабатываемых строк. Другие показатели оказались неинформативными.

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

Вот такие результаты у меня получились:

Вариант

Время выполнения, с.

Обработано строк

  3 мес. 6 мес. 3 мес. 6 мес.
А (традиционный) 4.9 10.2 1 626 647 3 195 284
Б (интервальный) 4.3 10.3 1 626 647 3 195 284
В (без группировки) 10.0 26.2 2 107 110 13 596 463
Г (с группировкой) 20.1 105.0 4 387 711 27 379 466
Д (эшелонный) 20.8 71.6 4 897 463 15 876 311

 

Варианты А и Б лидируют и не сильно отличаются друг от друга. Результат остальных довольно безрадостен.

Можно заключить: срез последних в один запрос реализовать можно. Но лучше — не надо.

Репозиторий тестовой конфигурации: github.com/boroda310/slice-slice-slice

Отсылки:

срез замер производительность запрос эксперимент

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 руб.

02.09.2020    119956    656    389    

701

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5622    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

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

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    1964    2    Yashazz    0    

29

Запрос 1С copilot

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

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6094    29    mkalimulin    23    

48

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

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

14.12.2023    1714    vandalsvq    7    

28

Объектная модель запроса "Схема запроса" 2

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

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

06.12.2023    5286    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    15958    skovpin_sa    14    

98
Вознаграждение за ответ
Показать полностью
Отзывы
25. ildarovich 7846 17.02.21 21:42 Сейчас в теме +10 $m
(24) Нет, не так.

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

Кстати, а индексирование по измерению "Номенклатура" в регистре сведений "ЦеныНоменклатуры" когда и зачем было отключено? Ну или почему оно "ведущим" не было сделано? Я имею ввиду тестовую конфигурацию.

Хотелось еще, чтобы вы вот такие варианты запроса (В) на вашем стенде попробовали (включив индексацию, разумеется). Такой:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Количество КАК Количество,
	100 * (ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) / ЦеныНоменклатуры.Цена КАК Скидка
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ПродажаТовараТовары.Цена < 0.9 * ЦеныНоменклатуры.Цена) 
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры.Период)
			И 1 НЕ В 
			(ВЫБРАТЬ 1 ИЗ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры2 
			ГДЕ (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры2.Номенклатура)
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры2.Период)
			И (ЦеныНоменклатуры2.Период > ЦеныНоменклатуры.Период))
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать

А также такой:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Количество КАК Количество,
	100 * (ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) / ЦеныНоменклатуры.Цена КАК Скидка
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ПродажаТовараТовары.Цена < 0.9 * ЦеныНоменклатуры.Цена) 
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры.Период)
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры2
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры2.Номенклатура)
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры2.Период)
			И (ЦеныНоменклатуры2.Период > ЦеныНоменклатуры.Период)
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода
	И ЦеныНоменклатуры2.Период ЕСТЬ NULL
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать

А мой запрос лучше применить вот в таком варианте:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Цена КАК ЦенаДокумента,
	МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ) * &Много + 0.9 * ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) - МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ)) * &Много КАК Оверскидка,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовараТовары.Количество КАК Количество,
	ПродажаТовараТовары.НомерСтроки КАК НомерСтроки
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ЦеныНоменклатуры.Период <= ПродажаТовара.Дата)
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО
	ПродажаТовара.Ссылка,
	ПродажаТовараТовары.Номенклатура,
	ПродажаТовараТовары.Цена,
	ПродажаТовара.Контрагент,
	ПродажаТовараТовары.Количество,
	ПродажаТовараТовары.НомерСтроки

ИМЕЮЩИЕ
	МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ) * &Много + 0.9 * ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) < МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ)) * &Много
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать
Ну и еще установок цен, чтобы было ближе к реальности, нужно побольше. Например, не 24, а 124. Их можно на 2,5 года растянуть. Начав с 01.01.2019, например. Это я к тому, что 9 записей в РС на номенклатуру - это вообще ни о чем. Нечего оптимизировать, никакие хитрые приемы не нужны и конкурса именно по срезу последних не получается.
user712426; Theose; aleksey2; antonio_i; Светлый ум; RibD; user1067792; Simonov_NPM; Serg O.; +9 1 Ответить
Остальные комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. kozusenok 52 15.02.21 13:09 Сейчас в теме
А мне ещё вот такой вариант приглянулся где-то тут на форуме
ВЫБРАТЬ
	ЦеныНоменклатуры.Период КАК Период,
	ЦеныНоменклатуры.Номенклатура КАК Номенклатура,
	ЦеныНоменклатуры.Цена КАК Цена
ПОМЕСТИТЬ ВсеЦеныНоменклатуры
ИЗ
	РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
	ЦеныНоменклатуры.Период <= &КонецПериода
;

ВЫБРАТЬ
	Продажи.Регистратор КАК Документ,
	Продажи.Контрагент КАК Контрагент,
	Продажи.Номенклатура КАК Номенклатура,
	Продажи.Количество КАК Количество,
	ВсеЦеныНоменклатуры.Цена КАК Цена
ИЗ
	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК Продажи
	ЛЕВОЕ СОЕДИНЕНИЕ ВсеЦеныНоменклатуры КАК ВсеЦеныНоменклатуры
	ПО Продажи.Номенклатура = ВсеЦеныНоменклатуры.Номенклатура
		И ВсеЦеныНоменклатуры.Период В
			(ВЫБРАТЬ
				МАКСИМУМ(ЦеныНоменклатуры.Период)
			ИЗ
				ВсеЦеныНоменклатуры КАК ЦеныНоменклатуры
			ГДЕ
				ЦеныНоменклатуры.Период <= Продажи.ПериодСекунда
				И ЦеныНоменклатуры.Номенклатура = Продажи.Номенклатура)
Показать
user712426; ildarovich; +2 Ответить
2. randomus 273 15.02.21 15:28 Сейчас в теме
(1) надеюсь, это сарказм ;)
3. randomus 273 15.02.21 18:33 Сейчас в теме
(2) я не поленился и замерял этот вариант. За первый квартал время выполнения 23 сек.
это очень плохой вариант. План запроса:
Прикрепленные файлы:
user712426; user1367144; t278; MGraf; shard; BigB; +6 Ответить
14. buganov 200 17.02.21 07:33 Сейчас в теме
(1) без обид, но запрос ужасный. Начиная от неограниченного количества кортежей снизу во временной таблице, заканчивая чтением регистра накопления как попало.
randomus; +1 Ответить
34. director04 3657 18.02.21 10:53 Сейчас в теме
(1) Использовать в соединении таблиц запрос - это губить производительность системы.
На малых объемах данных можно. На больших - повесите систему....
40. ildarovich 7846 19.02.21 10:05 Сейчас в теме
(34) Тем не менее, посмотрите результаты в (28). Объемы данных там не маленькие. Производительность не то, чтобы не погублена, а даже многократно спасена.
45. triviumfan 91 24.02.21 09:15 Сейчас в теме
(40) Опа, с возвращением! Сергей, можно ли от вас ждать новых статей? Совсем пропали.
4. RustIG 1301 16.02.21 17:04 Сейчас в теме
Почти год я собирался с мыслями. Потом провел эксперимент. Еще почти год созревал изложить это в виде статьи. Наконец, созрел :)

Коллеги, цените публикации!
у меня лично также - уходит много времени "чтобы собраться", "чтобы написать". реально, это труд.
Eillecho; Merkalov; Dunda; KEV8383; ardn; Drivingblind; randomus; biimmap; +8 Ответить
5. RustIG 1301 16.02.21 17:07 Сейчас в теме
(0) План запроса какой обработкой выводили? Что за зверь такой?
8. randomus 273 16.02.21 18:18 Сейчас в теме
(5) Стандартная консоль запросов с ИТС, галочка показать план запроса. Если что, в конфигурацию встроена. Не так красиво, как в профайлере, но для данного случая показателей достаточно
Serg O.; RustIG; +2 Ответить
6. RustIG 1301 16.02.21 17:18 Сейчас в теме
(0) Коллеги, не кидайте камнями. Но я пару-тройку подобных задач решал по другому.
Создал регистр сведений (иногда их несколько было, иногда одного достаточно - зависит от показателей отчета , который требуется Заказчику) - при проведении Реализации сохраняю в регистр сведений цены на каждый товар из реализации, скидку, цены на товар из общего регистра ЦеныНоменклатуры, ответственного.
Далее Отчет строю по этому регистру. Информация копится быстро, согласен, что сведения дублируются из других регистров -но такова суть управленческого учета - много регистров сведений и накоплений почти дублируют друг друг, отличаясь только одним-двумя измерениями.
Подобная схема реализации очень быстро внедряется, легко адаптируется при изменении ТЗ Заказчика.
Через год -два делаю свертку.

Плюс подобная задача возникает при расчете итоговых остатков на расчетных счетах на каждый день - для финансового учета и планирования. Подвести итоги пока не могу, процесс автоматизации финучета "для себя" временно приостановлен.
randomus; jONES1979; +2 Ответить
9. randomus 273 16.02.21 18:22 Сейчас в теме
(6) Конечно, если есть возможность хранить промежуточные результаты, то почему бы нет. Я просто протестил известные варианты известной вычислительной задачи.
16. Yashazz 4707 17.02.21 08:55 Сейчас в теме
(6) Разумеется, в общем случае архитектурное решение гораздо лучше, его заточить под конкретику можно. Но объём растёт. Равно как и поиграть с таблицами значений, пока они не убивают сеансовый кэш, иногда проще и в разы быстрее. Извечный поиск баланса между местом на диске, местом в кэше/оперативке и скоростью исполнения.
36. mixsture 18.02.21 11:17 Сейчас в теме
(6)
стр сведений (иногда их несколько было, иногда одного достаточно - зависит от показателей отчета , который требуется Заказчику) - при проведении Реализации сохраняю в регистр сведений цены на каждый товар из реализации, скидк


и я тоже за такое решение. Просто надо раз и навсегда признаться, что типовые сущности не позволяют выполнить такой запрос эффективно. Поэтому и следует использовать заранее подготовленные данные - этот подход очень распространен в конфигурациях, хорошо разделяет сложность задачи, убирая его с отчета, и хорошо модифицируется и поддерживается в дальнейшем.
Это, несомненно, сдвигает баланс системы с OLTP -> OLAP, что выливается в более долгое проведение доков при более быстром формировании отчетов.
randomus; RustIG; +2 Ответить
7. RustIG 1301 16.02.21 17:25 Сейчас в теме
(0) кому-то большие запросы - это неизбежность, с которой приходится мириться.... я стараюсь обходить большие запросы в прямом смысле слова - часто получаю ТаблицуЗначений из Запроса вместо Выборки. Далее в ТаблицеЗначений меняю сведения или обрабатываю строки, и далее окончательный результат возвращаю.
Опять-таки, не считаю что это единственно правильный метод, но архитектура красивого решения в этом и заключается, что мы используем баланс: минимум соединений таблиц в запросах - минимум физических таблиц для хранения информации.
Что-то подобное я пробовал описать в публикации, но при повторном прочтении, понимаю сам, что написал сложным языком. Поэтому соррян заранее: https://infostart.ru/1c/articles/195627/
mashinist; Yashazz; randomus; jONES1979; +4 Ответить
11. randomus 273 16.02.21 18:35 Сейчас в теме
(7) В таблицу значений - нормальное решение, тоже часто использую. С другой стороны, соединения - это основное назначение SQL-сервера. Он на них натаскан и оптимизирован :) Поэтому я наоборот стараюсь максимальное количество соединений отдать на выполнение SQL-серверу. Естественно, их надо грамотно строить и не использовать сложных условий в связях. Если не получается упростить условия, тогда лучше без них.
Со статьей ознакомлюсь, спасибо.
10. RustIG 1301 16.02.21 18:33 Сейчас в теме
(8) спасибо за статью и ответ. ловите вознаграждение.
randomus; +1 Ответить
12. randomus 273 16.02.21 18:47 Сейчас в теме
(10) спасибо! Мне пришла идея, как распорядится вознаграждением :) Я добавил еще 9 sm.
И все 10 получит тот, кто пришлет свой вариант решения, если он будет в один запрос и быстрее варианта В. Либо быстрее варианта А без ограничения количества запросов, подзапросов, временных таблиц
13. ilya2184 62 16.02.21 23:52 Сейчас в теме
Не пробовал индексировать поля соединения, например в традиционном варианте? Может получиться быстрее (а может и медленнее)
15. Yashazz 4707 17.02.21 08:51 Сейчас в теме
А кто-нибудь замерял, что в общем случае быстрее -
ПродажаТовара.Дата >= вт_ПериодыЦен.НачалоПериода И ПродажаТовара.Дата < вт_ПериодыЦен.КонецПериода
или
ПродажаТовара.Дата МЕЖДУ вт_ПериодыЦен.НачалоПериода И ДОБАВИТЬКДАТЕ(вт_ПериодыЦен.КонецПериода, СЕКУНДА, -1)

кто знает?
19. randomus 273 17.02.21 12:47 Сейчас в теме
(15) думаю, что примерно одинаково. позже проверю
20. randomus 273 17.02.21 15:28 Сейчас в теме
(15) проверил :) оценки в плане запроса одинаковые, но время выполнения у первого варианта немного меньше
22. Yashazz 4707 17.02.21 17:59 Сейчас в теме
(20) Спасибо. Вообще, Вам спасибо, дельная хорошая публикация.
17. Simonov_NPM 17.02.21 10:11 Сейчас в теме
Традиционный запрос
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ПродажиОбороты.Период КАК Дата
ПОМЕСТИТЬ вт_ДатыПродаж
ИЗ
	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, День, ) КАК ПродажиОбороты
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ЦеныНоменклатуры.Период,
	ЦеныНоменклатуры.Номенклатура,
	ЦеныНоменклатуры.Цена
ПОМЕСТИТЬ ВТ_Цены
ИЗ
	РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
	ЦеныНоменклатуры.ТипЦен = &ТипЦен
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	МАКСИМУМ(ВТ_Цены.Период) КАК Период,
	ВТ_Цены.Номенклатура КАК Номенклатура,
	вт_ДатыПродаж.Дата КАК Дата
ПОМЕСТИТЬ вт_ДатыАктуальныхЦен
ИЗ
	вт_ДатыПродаж КАК вт_ДатыПродаж
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Цены КАК ВТ_Цены
		ПО ВТ_Цены.Период <= вт_ДатыПродаж.Дата

СГРУППИРОВАТЬ ПО
	вт_ДатыПродаж.Дата,
	ВТ_Цены.Номенклатура
;

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

показал время 287 на 6600 записях

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



показал время 84 на 6600 записях

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

База УПП, Субд sql2012

Показатель i/o конечно значительно выше у плохого запроса.
user712426; Eeeehhhh; zqzq; +3 Ответить
46. triviumfan 91 24.02.21 09:21 Сейчас в теме
47. Simonov_NPM 24.02.21 10:00 Сейчас в теме
(46) Для того чтобы два раза не обращаться к физической таблице
18. BackinSoda 17.02.21 11:49 Сейчас в теме
А я думал, что "интервальный" является "традиционным".
Спасибо за статью !
21. ildarovich 7846 17.02.21 16:45 Сейчас в теме
Если разобраться: от чего зависит сравнительное время выполнения этих запросов, то результаты при заданных условиях окажутся очевидными без всякого вычислительного эксперимента. Кстати, коррелированный запрос (1), по-моему мнению, зря сбросили со счетов. По условиям эксперимента у вас одна номенклатура продается в среднем 18 раз за день, а меняет свою цену - раз в двадцать дней, то есть - 4,5 раза за квартал. Соединение самих с собой 4,5 записей с 4,5 записями (упрощаю, так как есть нелинейность) - это условия, в которых проблема тэта соединений вообще не заметна. То есть считать заново 18 раз в день то, что меняется раз в 20 дней просто глупо. Поэтому однозапросный метод, в котором на каждую дату все заново считается, здесь не подходит не про причине своей ущербности, а по причине избыточного повторения вычислений.

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

Так что ваши выводы справедливы не в общем, а частном случае соотношения числа записей в периодическом регистре и количества требуемых дат в множественном срезе последних, ИМХО.

Ну и, пользуясь случаем, прорекламирую тут свой метод индексирования интервалов для борьбы с фамильной болезнью периодических регистров сведений - деградацией производительности при росте количества записей.
zqzq; RustIG; +2 Ответить
23. Yashazz 4707 17.02.21 18:01 Сейчас в теме
(21) Вот да, от бизнес-смысла каждой конкретной задачи плясать надо, и выбирать решение именно исходя из ситуации.
24. randomus 273 17.02.21 21:11 Сейчас в теме
(21) В реальной жизни условная "переоценка" всегда реже условной "продажи".
Хотелось бы увидеть хоть один реальный обратный пример. Соответственно, мои выводы справедливы - в реальной жизни :)
25. ildarovich 7846 17.02.21 21:42 Сейчас в теме +10 $m
(24) Нет, не так.

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

Кстати, а индексирование по измерению "Номенклатура" в регистре сведений "ЦеныНоменклатуры" когда и зачем было отключено? Ну или почему оно "ведущим" не было сделано? Я имею ввиду тестовую конфигурацию.

Хотелось еще, чтобы вы вот такие варианты запроса (В) на вашем стенде попробовали (включив индексацию, разумеется). Такой:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Количество КАК Количество,
	100 * (ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) / ЦеныНоменклатуры.Цена КАК Скидка
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ПродажаТовараТовары.Цена < 0.9 * ЦеныНоменклатуры.Цена) 
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры.Период)
			И 1 НЕ В 
			(ВЫБРАТЬ 1 ИЗ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры2 
			ГДЕ (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры2.Номенклатура)
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры2.Период)
			И (ЦеныНоменклатуры2.Период > ЦеныНоменклатуры.Период))
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать

А также такой:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Количество КАК Количество,
	100 * (ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) / ЦеныНоменклатуры.Цена КАК Скидка
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ПродажаТовараТовары.Цена < 0.9 * ЦеныНоменклатуры.Цена) 
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры.Период)
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры2
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры2.Номенклатура)
			И (ПродажаТовара.Дата >= ЦеныНоменклатуры2.Период)
			И (ЦеныНоменклатуры2.Период > ЦеныНоменклатуры.Период)
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода
	И ЦеныНоменклатуры2.Период ЕСТЬ NULL
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать

А мой запрос лучше применить вот в таком варианте:
ВЫБРАТЬ
	ПродажаТовара.Ссылка КАК Ссылка,
	ПродажаТовараТовары.Цена КАК ЦенаДокумента,
	МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ) * &Много + 0.9 * ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) - МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ)) * &Много КАК Оверскидка,
	ПродажаТовара.Контрагент КАК Контрагент,
	ПродажаТовараТовары.Номенклатура КАК Номенклатура,
	ПродажаТовараТовары.Количество КАК Количество,
	ПродажаТовараТовары.НомерСтроки КАК НомерСтроки
ПОМЕСТИТЬ ВременнаяТаблица
ИЗ
	Документ.ПродажаТовара.Товары КАК ПродажаТовараТовары
		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПродажаТовара КАК ПродажаТовара
		ПО (ПродажаТовараТовары.Ссылка = ПродажаТовара.Ссылка)
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
		ПО (ПродажаТовараТовары.Номенклатура = ЦеныНоменклатуры.Номенклатура)
			И (ЦеныНоменклатуры.Период <= ПродажаТовара.Дата)
ГДЕ
	ПродажаТовара.Дата МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО
	ПродажаТовара.Ссылка,
	ПродажаТовараТовары.Номенклатура,
	ПродажаТовараТовары.Цена,
	ПродажаТовара.Контрагент,
	ПродажаТовараТовары.Количество,
	ПродажаТовараТовары.НомерСтроки

ИМЕЮЩИЕ
	МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ) * &Много + 0.9 * ЦеныНоменклатуры.Цена - ПродажаТовараТовары.Цена) < МИНИМУМ(РАЗНОСТЬДАТ(ЦеныНоменклатуры.Период, &КонецПериода, ДЕНЬ)) * &Много
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КОЛИЧЕСТВО(*) КАК Поле1
ИЗ
	ВременнаяТаблица КАК ВременнаяТаблица
Показать
Ну и еще установок цен, чтобы было ближе к реальности, нужно побольше. Например, не 24, а 124. Их можно на 2,5 года растянуть. Начав с 01.01.2019, например. Это я к тому, что 9 записей в РС на номенклатуру - это вообще ни о чем. Нечего оптимизировать, никакие хитрые приемы не нужны и конкурса именно по срезу последних не получается.
user712426; Theose; aleksey2; antonio_i; Светлый ум; RibD; user1067792; Simonov_NPM; Serg O.; +9 1 Ответить
28. Serg O. 224 18.02.21 09:38 Сейчас в теме
согласен, товаров и установок цен должно быть больше

сравнил запрос А и Ваши запрос на "реальной" торговой базе за 1 месяц (январь 2021)
установки цен идут ежедневно по несколько 4-10 тыс. товаров (133 тыс. записей рс.ЦеныНоменклатурын за месяц )
результат запроса: 18 359

"лучший" запрос А - выполнялся: 65 - 66 сек,
Ваш 1 запрос: 2 сек !!!
Ваш 2 запрос: 15 сек
Ваш 3 запрос: 1,25 - 1,32 сек (при Много = 31 день) - наилучший результат!
ildarovich; +1 Ответить
32. randomus 273 18.02.21 10:01 Сейчас в теме
(28) откуда я знаю как вы адаптировали "мои" запросы к реальной базе?

И что такое "много = 31 день" в "моем 3 запросе"?

Много - это в запросе Ильдаровича, и оно не в днях измеряется а в рублях.
и 31 в таком случае это не много и запрос вероятно работает не правильн.

Похоже, надо запрещать комментарии, а то холивар разгорается :)

Напишите свою статью лучше. Может я прочитаю и прояснится в голове
38. Serg O. 224 19.02.21 07:41 Сейчас в теме
(32) за Вашу статью спасибо и большой +

Данные по времени из более наполненной базы торговли я привёл для (25) ildarovich
42. randomus 273 19.02.21 12:57 Сейчас в теме
(38) Извините, неправильно понял вас. Если это результаты запросов из (25) то действительно интересно, есть над чем подумать, спасибо.
39. ildarovich 7846 19.02.21 09:42 Сейчас в теме
(28) Спасибо, очень интересно, есть о чем подумать. И, возможно, еще скорректировать выводы в (37). Получается, работа с временной таблицей (созданием и выборкой из нее) достаточно много времени на этих данных отнимает.

Единственно, &Много действительно должно быть не 31, а больше (зависит от диапазона данных). Больше диапазона изменения ресурса. Поэтому 10 000, которые в тесте - надежнее. Проверить можно, сравнив количество в результате запроса.

Хотя, если разница между 0.9 установленной цены и ценой продажи не превышают 31 рубля, результат будет тем же. А на скорости это сказываться не должно.

Интересен результат коррелированного запроса.
29. randomus 273 18.02.21 09:48 Сейчас в теме
(25)
Нет, не так.


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

Кстати, а индексирование по измерению "Номенклатура" в регистре сведений "ЦеныНоменклатуры" когда и зачем было отключено? Ну или почему оно "ведущим" не было сделано? Я имею ввиду тестовую конфигурацию.


Я начинаю сомневаться в продуктивности дальнейшего спора.

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

Я, кстати, пробовал индексировать поле Номенклатура отдельно - результаты немного ухудшались. Возможно, сервер тратил время на выбор нужного индекса.

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

Ваши варианты я попробую, сейчас тестового стенда нет под рукой. Но мне кажется - там только косметические улучшения
33. ildarovich 7846 18.02.21 10:16 Сейчас в теме
(29)
Не было оно отключено
Знаете, мне очень понравилось оформление тестовой конфигурации - было удобно и приятно с ней работать. Еще удобнее то, что я скачал ее на гитхабе, куда вы ее так любезно выложили. И вот после того как я загрузил конфигурацию из файлов, я и получил снятый флажок в ведущем измерении "Номенклатура" и отключенный по нему индекс. - Попробуйте загрузить те же файлы в чистую конфигурацию - сами это увидите.
Стыдно этого не знать
Если бы мне было стыдно от всего, чего я не знаю - давно бы сгорел от этого стыда.
Переживаю я не за свой вариант, а, как всегда, за "научную истину".
Merkalov; +1 Ответить
35. randomus 273 18.02.21 11:07 Сейчас в теме
(33)Всё правильно, так и было задумано. Потому что, в данном случае, достаточно индексов, которые 1с создает по умолчанию.
В гугле поиск "индексы 1с" первая ссылка.
Можно проверить средствами SQL сервера
37. ildarovich 7846 18.02.21 13:58 Сейчас в теме
(35) Вот про это я и спрашивал в (25): почему было отключено. Посмотрел по ссылке, да, все так, индекс и без этого строится.

Вообще, ничего плохого статья не советует. Я бы вообще не спорил, если бы статья называлась: Когда выгодно использовать временные таблицы на типовом примере срезов последних. Обоснующий выигрыш здесь, в основном, не из-за разного подхода к срезу в этих запросах (за исключением Д), а из-за кэширования цен на каждый день.

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

Получается, я был не совсем прав, говоря о том, что для выигрыша (В) или (Д) нужно больше записей в РС, дело больше в количестве продаж номенклатуры в день, ну или в периодичности регистра.

Очищая все эти запросы от шелухи (то есть ставя их в равные условия), получаем ключевой вопрос сравнения подходов (А) и (В): что выгоднее - использовать агрегат "максимум" и записать период цены во временную таблицу, а затем запросом по сверхселективному индексу извлечь цену или использовать второе тэта соединение? Думаю, когда записей станет больше и больше, (В) станет проигрывать, Остается (Д) - вычисления (их еще можно подкрутить, использовать функцию подсчета остатка) против подсчета максимума и записи во временную таблицу. Меня в свое время удивило, что подсчет максимума при наличии индекса по соответствующему полю его не использует. Если это так в каких-либо СУБД, то (Д) - в любом случае проигрывает.

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

По поводу конкурса на придумывания лучших запросов, чем (А) и (В) могу сказать, что то, что предложено в (25) - это своего рода читерство. Чтобы превзойти такой запрос как (А) в общем каким-либо новым хитрым способом нужны условия (а они бывают в жизни), когда записей в РС гораздо больше. Если согласуем такие условия - могу попробовать...
41. randomus 273 19.02.21 12:49 Сейчас в теме
(37) Согласен на ваши условия. Попробуйте.

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

Кстати, тот факт, что я отключил параллелизм, почему-то никто не отметил. Но в реалиях-то он есть, и какие-то запросы параллелятся лучше, какие-то хуже. Тоже надо исследовать, если по хорошему.

Тета-соединения в варианте Б меня тоже смущали, поэтому он и вызывал недоверие. Но, как ни странно, в моих условиях показал себя хорошо
44. randomus 273 23.02.21 22:25 Сейчас в теме
(25) Наконец дошли руки запустить эти запросы на первоначальном стенде.

Сразу только период 6 мес.:

1) 16 сек. - весьма неплохо. Но запрос не один - есть коррелированный.
2) 22.3 сек. - улучшенный мой (В) вариант, за счет доп. отбора в соединении.
3) 46.5 сек. - результат улучшен, математику оптимизировали.

Ну в общем, 2-й запрос удовлетворяет условиям конкурса.
Если других вариантов не будет, признаем его победителем.

Отмечу, что 1-й запрос - очень элегантное решение, мне понравилось. По сути, 1-й и 2-й запрос делают одно и тоже, но во втором приходится перебрать гораздо больше строк. И исправить без коррелированного запроса никак не получается. @ildarovich - отдельное спасибо за дельные комментарии.
27. Serg O. 224 18.02.21 08:57 Сейчас в теме
(24) вы не совсем правы
установки цен могут (и идут!) каждый (рабочий, хотя бы) день

и да, товаров может быть намного больше 30-50 тыс. товаров
и умножаем это на 5-10 и более типов "базовых" цен!

тогда за месяц уже 1-1,5 млн. записей будет по 1 типу цен!
т.е. 5-15 млн. в "нашей реальности"

анализ на 1,5 тыс. наверное будет отличаться от 1,5 млн.
(и SQL планировщик иногда сам "решит" как лучше)
условия в соединении таблиц - вообще зло... и "не рекомендуется 1С"

на "нашей" базе УТ - запрос А за 1 месяц (январь 2021) - 66 сек - результат 18 359
если заменить Документ.ПродажаТовара -> Документ.РеализацияТоваровУслуг

и ошибка в запросе А - деление на 0 в поле Скидка
100 * (ЦеныНоменклатуры.Цена - РеализацияТоваровУслугТовары.Цена) / ЦеныНоменклатуры.Цена

пришлось заменить на условие
выбор когда ЦеныНоменклатуры.Цена>0
тогда 100 * (ЦеныНоменклатуры.Цена - РеализацияТоваровУслугТовары.Цена) / ЦеныНоменклатуры.Цена
иначе -100
конец
30. randomus 273 18.02.21 09:50 Сейчас в теме
(27)
установки цен могут (и идут!) каждый (рабочий, хотя бы) день

зачем тогда нужен срез последних?
31. Serg O. 224 18.02.21 09:55 Сейчас в теме
(30) цены (для примера) могут расти... а реально меняются вверх-вниз!

и задача тестовая (которая в запросе А) не на срез последних на конец периода...
а на получение продаж со скидкой > 10%

+ документы часто могут перепроводить / менять цены "задним числом"
и нужны цены на старую дату постоянно
26. Serg O. 224 18.02.21 08:43 Сейчас в теме
согласен с ildarovich, надо массивы побольше анализировать
1,5 -3 тыс записей в регистре это маловато...

Сделайте установки на каждый (рабочий, хотя бы) день
и да, товаров надо побольше 30-50 тыс. товаров
тогда за месяц уже 1-1,5 млн. записей хотя бы будет
это "ближе" к реальности...

для случайности, можно для теста цены +1р. на каждый день сделать
или по курсу $ например сделать за период
(доллар падает, цены растут вопреки логике?!)

кстати группировка хоть и "накладнее", но "сворачивает" лишние записи...
и без неё иногда не обойтись, + группировка делает доп.индексацию в ВТ
только это делается по всем полям группировки! а их "слишком много" вроде бы
гляда на запрос Г и Д не очень понятно... зачем там поле НомерСтроки ?

и да, большой + за проделанную работу, очень интересная статья
43. avega67 23.02.21 17:38 Сейчас в теме
Замечательная статья. И подана тоже очень хорошо.

По варианту "Б" только, по-моему, во 2-ом запросе пакета при формировании врем.таблицы ВТ_ПериодыЦен нужно:
КОНЕЦПЕРИОДА(ЕСТЬNULL(МИНИМУМ(ЦеныЗаПериод_Конец.Период), &КонецПериода), ДЕНЬ) КАК КонецПериода
Оставьте свое сообщение