| 
			
			 | 
		#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, номенклатура, остатки, производительность, прайс | 
| 
	
	 | 
	
		
  |