Вот запрос, который проставляет цены в документ (конфа Розница). Нюанс в том, что если цена за характеристику указана, то используется эта цена, если не указана - то цена без характеристики.
В общем, оказалось, что если запускать по всем товарам на остатках, непропорционально сильно тормозит на файловой версии (2 часа работает) на 4000 позициях и 5 секунд на 200 позициях.
Думайте, какой способ я нашел, чтобы ускорить код. ;-)
Метод настоящего гуру. Потом опубликую, если не догоните.
Хотя бы идеи предложите.
В общем, оказалось, что если запускать по всем товарам на остатках, непропорционально сильно тормозит на файловой версии (2 часа работает) на 4000 позициях и 5 секунд на 200 позициях.
Думайте, какой способ я нашел, чтобы ускорить код. ;-)
Метод настоящего гуру. Потом опубликую, если не догоните.
Хотя бы идеи предложите.
ВЫБРАТЬ
ТабличнаяЧастьДокумента.Номенклатура КАК Номенклатура,
ТабличнаяЧастьДокумента.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
ТабличнаяЧастьДокумента.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
ЕСТЬNULL(ЦеныНоменклатурыМагазиновСрезПоследних.Цена, ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Цена) КАК Цена,
ЕСТЬNULL(ЦеныНоменклатурыМагазиновСрезПоследних.ЕдиницаИзмерения, ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.ЕдиницаИзмерения) КАК ЕдиницаИзмеренияЦены,
ТабличнаяЧастьДокумента.НомерСтроки КАК НомерСтроки
ИЗ
ВременнаяТабличнаяЧастьДокумента КАК ТабличнаяЧастьДокумента
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыМагазинов.СрезПоследних(
&ДатаДокумента,
Номенклатура В (&МассивНоменклатуры)
И ХарактеристикаНоменклатуры В (&МассивХарактеристик)
И Магазин = &Магазин) КАК ЦеныНоменклатурыМагазиновСрезПоследних
ПО ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследних.Номенклатура
И ТабличнаяЧастьДокумента.ХарактеристикаНоменклатуры = ЦеныНоменклатурыМагазиновСрезПоследних.ХарактеристикаНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатурыМагазинов.СрезПоследних(
&ДатаДокумента,
Номенклатура В (&МассивНоменклатуры)
И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
И Магазин = &Магазин) КАК ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик
ПО ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура
ПоказатьОтветы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
ну фиг знает, без базы-то.. теоретическое программирование такое программирование
навскидку, идея в том, что соединение надо сделать одно. Добавить ПустуюСсылку в &МассивНоменклатуры и соединиццо. Единственное, надо заранее в ТЧ предпросчитать те позиции, где какбэ пустая Характеристика. Например, загодя соединившись с этим регистром перескинув ТЧ с правдивой характеристикой в ВТ.
Вообще, проседание в 2 часа - это лихо. Хоть и на файловой базе. Значит прут тонны лишних огромных джоинов. Самое быстрое, что приходит на ум в связи с этим - тотальный предпросчет со скидками промежуточных данных в ВТ.
Чо еще... Ну индексы можно выставить...
Я обычно в таких случаях серьёзно упрощаю запрос до "выбрать первые 100 из .. где.. " и дальше, добавляя новые куски, смотрю после чего резко просело.
навскидку, идея в том, что соединение надо сделать одно. Добавить ПустуюСсылку в &МассивНоменклатуры и соединиццо. Единственное, надо заранее в ТЧ предпросчитать те позиции, где какбэ пустая Характеристика. Например, загодя соединившись с этим регистром перескинув ТЧ с правдивой характеристикой в ВТ.
Вообще, проседание в 2 часа - это лихо. Хоть и на файловой базе. Значит прут тонны лишних огромных джоинов. Самое быстрое, что приходит на ум в связи с этим - тотальный предпросчет со скидками промежуточных данных в ВТ.
Чо еще... Ну индексы можно выставить...
Я обычно в таких случаях серьёзно упрощаю запрос до "выбрать первые 100 из .. где.. " и дальше, добавляя новые куски, смотрю после чего резко просело.
Так как время исполнения запроса имеет нелинейную зависимость от входных данных, решение состоит в следующем:
Запрос выполняем в цикле небольшими порциями. Для этой задачи 4000 позиций эквивалентны 20 порциям по 200 позиций. Таким образом время выполнения сократися с 2 часов до 20*5сек = 100 сек.
В силу сильной нелинейности можно предположить, что время выполнения запроса для одной позиции составляет милисекунду. Простой расчет даст время выполнения 4000 * 0,001 = 4сек! Плюс время на выполнение самого цикла.
Миф фирмы 1С, что запросы в цикле моветон разоблачен:-)
Запрос выполняем в цикле небольшими порциями. Для этой задачи 4000 позиций эквивалентны 20 порциям по 200 позиций. Таким образом время выполнения сократися с 2 часов до 20*5сек = 100 сек.
В силу сильной нелинейности можно предположить, что время выполнения запроса для одной позиции составляет милисекунду. Простой расчет даст время выполнения 4000 * 0,001 = 4сек! Плюс время на выполнение самого цикла.
Миф фирмы 1С, что запросы в цикле моветон разоблачен:-)
без вникания в нюансы:
Сделать выборку по всем ценам с отбором только по номенклатуре;
для объединения дать условие ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура или ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
Сделать выборку по всем ценам с отбором только по номенклатуре;
для объединения дать условие ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура или ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
Рискну предположить, что суть проблемы не в том, что нужно еще найти цену для пустой характеристики.
Проблема в соединении больших таблиц при отсутствии подходящих индексов.
Трудоемкость здесь примерно 4000 х (4000+4000).
То есть даже если убрать второе соединение, порядок времени выполнения запроса (4000 х 4000) останется тем же (1? час для 4000 элементов).
Поэтому, кажется, ответ должен быть в том, чтобы использовать не соединение, а группировку по номенклатуре, объединив табличную часть и срез (срезы последних).
Это стандартный путь ускорения запросов в файловых базах.
Можно предположить, что в них реализован единственный способ соединения: nested loop, тогда как в SQL при отсутствии подходящих индексов используется еще hash join и merge join.
Ну а группировка по сути моделирует соединение слиянием и должна дать существенный выигрыш.
Интересно было бы знать, намеренно ли в файловой базе не сделали hash join и merge join, чтобы усилить преимущество более дорогой версии.
После первого этапа оптимизации можно посмотреть на необходимость срезов последних, которые в файловом варианте, вероятно, тоже не слишком эффективны.
Проблема в соединении больших таблиц при отсутствии подходящих индексов.
Трудоемкость здесь примерно 4000 х (4000+4000).
То есть даже если убрать второе соединение, порядок времени выполнения запроса (4000 х 4000) останется тем же (1? час для 4000 элементов).
Поэтому, кажется, ответ должен быть в том, чтобы использовать не соединение, а группировку по номенклатуре, объединив табличную часть и срез (срезы последних).
Это стандартный путь ускорения запросов в файловых базах.
Можно предположить, что в них реализован единственный способ соединения: nested loop, тогда как в SQL при отсутствии подходящих индексов используется еще hash join и merge join.
Ну а группировка по сути моделирует соединение слиянием и должна дать существенный выигрыш.
Интересно было бы знать, намеренно ли в файловой базе не сделали hash join и merge join, чтобы усилить преимущество более дорогой версии.
После первого этапа оптимизации можно посмотреть на необходимость срезов последних, которые в файловом варианте, вероятно, тоже не слишком эффективны.
(7) Вот такой запрос обрабатывает 4000 позиций за 0.822 секунды Глубина истории цен в тесте была равна 5-ти.
ВЫБРАТЬ
ВременнаяТабличнаяЧастьДокумента.НомерСтроки,
ВременнаяТабличнаяЧастьДокумента.Номенклатура,
ВременнаяТабличнаяЧастьДокумента.ХарактеристикаНоменклатуры,
ВременнаяТабличнаяЧастьДокумента.ЕдиницаИзмерения,
NULL КАК Цена
ПОМЕСТИТЬ Объединение
ИЗ
ВременнаяТабличнаяЧастьДокумента КАК ВременнаяТабличнаяЧастьДокумента
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
0,
ЦеныНоменклатурыМагазиновСрезПоследних.Номенклатура,
ЦеныНоменклатурыМагазиновСрезПоследних.ХарактеристикаНоменклатуры,
NULL,
ЦеныНоменклатурыМагазиновСрезПоследних.Цена / ЦеныНоменклатурыМагазиновСрезПоследних.ЕдиницаИзмерения.Коэффициент
ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов.СрезПоследних(
&ДатаДокумента,
Номенклатура В (&МассивНоменклатуры)
И Магазин = &Магазин) КАК ЦеныНоменклатурыМагазиновСрезПоследних
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
0,
ЦеныНоменклатурыМагазиновСрезПоследних.Номенклатура,
ХарактеристикиНоменклатуры.Ссылка,
NULL,
-ЦеныНоменклатурыМагазиновСрезПоследних.Цена / ЦеныНоменклатурыМагазиновСрезПоследних.ЕдиницаИзмерения.Коэффициент
ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов.СрезПоследних(
&ДатаДокумента,
Номенклатура В (&МассивНоменклатуры)
И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
И Магазин = &Магазин) КАК ЦеныНоменклатурыМагазиновСрезПоследних
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиНоменклатуры
ПО ЦеныНоменклатурыМагазиновСрезПоследних.Номенклатура = ХарактеристикиНоменклатуры.Владелец
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
МАКСИМУМ(Объединение.НомерСтроки) КАК НомерСтроки,
Объединение.Номенклатура КАК Номенклатура,
Объединение.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
МАКСИМУМ(Объединение.ЕдиницаИзмерения) КАК ЕдиницаИзмерения,
МАКСИМУМ(Объединение.Цена) КАК Цена
ИЗ
Объединение КАК Объединение
СГРУППИРОВАТЬ ПО
Объединение.Номенклатура,
Объединение.ХарактеристикаНоменклатуры
ИМЕЮЩИЕ
МАКСИМУМ(Объединение.НомерСтроки) > 0
Показать
Авторский вариант здесь.
Ларчик просто открывался - на вайлофое версии хреново работает объединение со срезом последних...
Так вот работает быстро и в файловой, и в SQL версии.
Тонкие такие нюансы, головой не понять, только профайлером. (Замером производительности).
Но реально тормозило.
Ларчик просто открывался - на вайлофое версии хреново работает объединение со срезом последних...
Так вот работает быстро и в файловой, и в SQL версии.
Тонкие такие нюансы, головой не понять, только профайлером. (Замером производительности).
Но реально тормозило.
ВЫБРАТЬ
Т.Цена,
Т.Номенклатура,
Т.ХарактеристикаНоменклатуры,
Т.ЕдиницаИзмерения
ПОМЕСТИТЬ ТЦены
ИЗ
РегистрСведений.ЦеныНоменклатурыМагазинов.СрезПоследних(
&ДатаДокумента,
Номенклатура В (&МассивНоменклатуры)
И (ХарактеристикаНоменклатуры В (&МассивХарактеристик)
ИЛИ ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка))
И Магазин = &Магазин) КАК Т
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ТабличнаяЧастьДокумента.Номенклатура КАК Номенклатура,
ТабличнаяЧастьДокумента.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
ТабличнаяЧастьДокумента.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
ЕСТЬNULL(ЦеныНоменклатурыМагазиновСрезПоследних.Цена, ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Цена) КАК Цена,
ЕСТЬNULL(ЦеныНоменклатурыМагазиновСрезПоследних.ЕдиницаИзмерения, ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.ЕдиницаИзмерения) КАК ЕдиницаИзмеренияЦены,
ТабличнаяЧастьДокумента.НомерСтроки КАК НомерСтроки
ИЗ
ВременнаяТабличнаяЧастьДокумента КАК ТабличнаяЧастьДокумента
ЛЕВОЕ СОЕДИНЕНИЕ ТЦены КАК ЦеныНоменклатурыМагазиновСрезПоследних
ПО ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследних.Номенклатура
И ТабличнаяЧастьДокумента.ХарактеристикаНоменклатуры = ЦеныНоменклатурыМагазиновСрезПоследних.ХарактеристикаНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ ТЦены КАК ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик
ПО ТабличнаяЧастьДокумента.Номенклатура = ЦеныНоменклатурыМагазиновСрезПоследнихБезХарактеристик.Номенклатура
Показать
(11) Да, проблема была не в соединении со срезами последних. Так, что ответ (7) для данной задачи не подходит. Хотя решение (8) тоже быстрое. Корень проблемы оказался в проверке
а конкретнее - в условии "И". Видимо, система декартово соединяет эти таблицы (4000х4000), а затем строит соединение с ними. Впредь будем осторожнее с условиями "И" в параметрах виртуальных таблиц. Спасибо за этот пример!
Номенклатура В (&МассивНоменклатуры) И ХарактеристикаНоменклатуры В (&МассивХарактеристик)
Внимание! Тема сдана в архив
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот