|
|
#1 |
|
Участник
|
Формирование прайс-листа в Axapta. Проблемы производительности.
Задача сформировать прайс-лист, т.е. вывести все позиции, которые находятся на складе X в количестве больше Y (частный случай >0). Простейшее решение выполнить следующий запрос:
X++: Select from InventSum join InventDim Where InventSum.InventDimId == InventDim.InventDimId && InventSum.AvailPhysical > Y && InventDim.InventLocationId = X Вопрос как лучше решать данную задачу в Axapta? Кто какие подходы для этого использует? |
|
|
|
|
#2 |
|
Участник
|
как решено у нас:
внешний цикл по номенклатуре, с фильтром заблокированных и др ограничения. внутри находим количество на складе, цену, накладываем допусловия и ограничения, если все ОК, то добавляем в tmpTable. вывод |
|
|
|
|
#3 |
|
Участник
|
Цитата:
так как выборка идет не по индексам
С совсем тяжелых случаях (если inventSum и InventDim - очень большие) можно сделать денормализацию данных. Создать поле склад в InventSum и индексы повесить. Тем самым избавимся от джоина. Намного легче запрос получится. |
|
|
|
|
#4 |
|
Участник
|
Мешает то, что непонятно каким должен быть этот индекс. По полю AvailPhysical? Не думаю, что индекс по вещественному полю увеличит производительность.
Сделать-то можно, только вариантов очень много и приходится выбирать какой из них лучше, чем сейчас и занимаюсь. |
|
|
|
|
#5 |
|
Участник
|
Цитата:
Простейшее решение - взять готовый отчет Критические запасы http://forum.mazzy.ru/index.php?showtopic=1842 |
|
|
|
| За это сообщение автора поблагодарили: konopello (1). | |
|
|
#6 |
|
Участник
|
Цитата:
цикл по номенклатуре с учетом всех ограничений - более 50000 записей, количество записей в прайс-листе - около 3000. Таким образом для каждой номенклатуры нужно выполнить запрос к InventSum по ItemId и суммировать кол-во. Такой запрос выполняется примерно 1 сек. (точно не анализировал, но запрос первой попавшейся НЕ на реально загруженном сервере дало именно такой результат). То есть общий цикл будет выполняться ну очень долго. Если я ошибаюсь в рассуждениях, поправьте меня. |
|
|
|
|
#7 |
|
Участник
|
Цитата:
А какая у этого всего производительность?
|
|
|
|
|
#8 |
|
SAP
|
Цитата:
Простейшее решение не такое.
Простейшее решение - взять готовый отчет Критические запасы http://forum.mazzy.ru/index.php?showtopic=1842 |
|
|
|
|
#9 |
|
Участник
|
Цитата:
Сообщение от Lucky13
Задача сформировать прайс-лист, т.е. вывести все позиции, которые находятся на складе X в количестве больше Y (частный случай >0). Простейшее решение выполнить следующий запрос:
X++: Select from InventSum join InventDim Where InventSum.InventDimId == InventDim.InventDimId && InventSum.AvailPhysical > Y && InventDim.InventLocationId = X А выгрузка прайс-листа - задача в общем лсучае сложная, вон, mazzy даже людей подбирает, исходя из того, как они с ней справляются ![]() Цитата:
Сообщение от Lucky13
К тому же это только пример, реально обычно нужно еще откуда-то достать цену товара и сгруппировать данные каким-либо образом, например по той же цене, так как клиенты чаще всего не любят когда одна и та же номенклатура повторяется в прайсе несколько раз. В итоге получается очень тяжелый запрос. Кто какие подходы для этого использует?
Подумайте также о том, что InventSum у вас может постоянно блокироваться при обработке движений по номенклатуре, а вы, пытаясь сделать по ней мега-запрос выгрузки прайс-листа, в свою очередь, будете блокировать других пользователей. Поэтому, опять же, кучка мелких подзапросов будет в общем случае предпочтительнее одного мега-запроса, который сначала будет ждать освобождения кучи блокировок, а потом сам надолго заблокирует таблицу, и без того являющуюся зачастую узким местом в системе. Затем, вам наверняка потребуется предоставить пользователю возможность группировать номенклатуру в выгрузке по различным критериям: либо по бренду, либо по какому-нить классификатору номенклатуры, либо еще по чему-то... Не так давно пришлось приделывать такую сортировку, плюс немного оптимизировать выгрузку прайс-листа, в котором используется довольно много условных критериев, в результате выгрузка (на псевдокоде) получилась примерно такая: Код: инициализировать канал вывода // отдельный метод
если выгрузка в csv/Excel
сделать то-то
если выгрузка в другую базу SQL
сделать что-то другое
вывести заголовок (header) // отдельный метод
сбросить значения предыдущего бренда и классификатора
построить запрос выборки номенклатуры // отдельный метод
switch по типу сортировки
если сортировка по бренду
запрос - таблица_брендов join InventTable
если сортировка по иерархическому классификатору номенклатуры
запрос - таблица_классификации join InventTable join таблица_брендов
установить фильтры по брендам // отдельный метод
установить фильтры по номенклатуре // отдельный метод
создать QueryRun с созданным запросом по номенклатуре
цикл, пока QueryRun.next() == true
если QueryRun.changed(таблица_брендов)
если текущий бренд не должен экспортироваться // отдельный метод
установить флаг пропуска бренда
если установлен флаг пропуска бренда
continue
получить необходимве данные по текущей номенклатуре
если номенклатура не должна экспортироваться // отдельный метод
continue
switch по типу сортировки
если сортировка по бренду
если текущий бренд != предыдущий бренд
вывести заголовок бренда // отдельный метод
запомнить бренд как предыдущий
если сортировка по иерархическому классификатору номенклатуры
если текущий код классификатора не равен предыдущему
вывести стек заговлоков классификатора // отдельный метод
запомнить код классификатора как предыдущий
сбросить переменные, используемые для получения цен, и флаги
цикл по ценовым группам
если ценовая группа не должна экспортироваться // отдельный метод
// и это отдельный метод
если номенклатура с "неэкспортируемой" ценой должна пропускаться
установить флаг пропуска номенклатуры
break
continue
получить цену (PriceDiscTable) по данной ценовой группе
// опять отдельный метод
если цена (т.е. PriceDiscTable) не должна экспортироваться
// copy-paste из проверки ценовых групп
если номенклатура с "неэкспортируемой" ценой должна пропускаться
установить флаг пропуска номенклатуры
break
continue
обработать данные по цене номенклатуры // отдельный метод
если выгрузка в csv/Excel
сделать то-то
если выгрузка в другую базу SQL
сделать что-то другое
если установлен признак пропуска номенклатуры
continue
выгрузить данные по текущей номенклатуре // отдельный метод
вывести заголовок (footer) // отдельный метод
деинициализировать канал вывода // отдельный метод |
|
|
|
|
#10 |
|
Участник
|
Цитата:
Сообщение от gl00mie
Подумайте также о том, что InventSum у вас может постоянно блокироваться при обработке движений по номенклатуре, а вы, пытаясь сделать по ней мега-запрос выгрузки прайс-листа, в свою очередь, будете блокировать других пользователей. Поэтому, опять же, кучка мелких подзапросов будет в общем случае предпочтительнее одного мега-запроса, который сначала будет ждать освобождения кучи блокировок, а потом сам надолго заблокирует таблицу, и без того являющуюся зачастую узким местом в системе.
|
|
|
|
|
#11 |
|
Участник
|
Это было навеяно местной спецификой экспорта прайс-листов в другие SQL-базы
На форуме упоминалось, что если делать запрос с inner join и выбирать в нем одну из таблиц для обновления, то заблокированными оказываются все таблицы из запроса.
|
|
|
|
|
#12 |
|
Участник
|
Цитата:
Сообщение от gl00mie
Если она исчисляется не миллионами, то лучше, вероятно, сделать выгрузку, перебирающую все номенклатуры (с определенными фильтрами, скажем, по бренду), а уже внутри этого перебора делающую проверку на остатки по определенному складу, на соответствие выгружаемых цен определенным критериями, etc.
Запрос: X++: while select inventTable where ... { } Если в цикл добавить запрос на выборку запасов в наличии X++: select sum(AvailPhysical) from inventSum join maxof(recid) from InventDim where inventSum.InventDimId == inventDim.inventDimId && inventSum.ItemId == inventTable.ItemId && inventSum.Closed == NoYes::No && inventDim.InventLocationId == 'склад' Так вот - такой цикл выполняется очень долго. Честно ждал полчаса, но безрезультатно. "Мега-запрос" хотя и имеет массу недостатков, но выполняется максимум за 3 минуты. Вопрос что здесь не так, почему такое расхождение теории с практикой? |
|
|
|
|
#13 |
|
Участник
|
Цитата:
Сообщение от Lucky13
Запрос:
X++: while select inventTable where ... { } X++: select sum(AvailPhysical) from inventSum join maxof(recid) from InventDim where inventSum.InventDimId == inventDim.inventDimId && inventSum.ItemId == inventTable.ItemId && inventSum.Closed == NoYes::No && inventDim.InventLocationId == 'склад' Цитата:
|
|
|
| Теги |
| inventsum, inventtable, номенклатура, остатки, производительность, прайс |
|
|
|