|  | 
|  22.06.2007, 07:41 | #1 | 
| Участник | Почему join запрос разбивается на подзапросы!? 
			
			Axapta 3.0 SP 3 Имеем запрос: Код:     while select _rassetTable
        index RAssetNumIdx
        where _rassetTable.VGP_PropertyTax          == NoYes::Yes
    join firstonly _rassetTrans
        index TransTypeIdx
        where _rassetTrans.AccountNum               == _rassetTable.AccountNum          &&
              _rassetTrans.AssetTransType           == RAssetTransType::Acquisition     &&
              _rassetTrans.TransDate                <= reportDateEnd
    join firstonly _ledgerTrans
        index VGP_LedgerLinkIdx
        where _ledgerTrans.VGP_LedgerLinkId         == _rassetTrans.VGP_LedgerLinkId    &&
              _ledgerTrans.VGP_LedgerLinkModuleRef  == VGP_LedgerLinkModuleRef::RAsset  &&
              _ledgerTrans.Voucher                  == _rassetTrans.Voucher             &&
              _ledgerTrans.TransDate                == _rassetTrans.TransDate
{
	…….
	//Не значительный код, заполняется мап
}Кол-во Select 4837 !!!!!?!?!? Почему?! Запрос отрабатывает порядка 25 минут Написал такой же запрос в SQL Enterprise Manager отработал за 5 секунд!! Прямой запрос, вставлять в код не очень хочется … .. . Подскажите в чём дело и что можно сделать?! 
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  22.06.2007, 09:25 | #2 | 
| Участник | 
			
			Хм. А пробовали убрать firstonly? Вполне возможно, что для каждой записи rAssetTable делается поиск записи соответствия свой вместо простого объединения таблиц. (как будто бы join вообще не было, а в теле while Вы отдельно искали требуемые записи) Хотя, это всего лишь предположение - возможно кто-то поправит. | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  22.06.2007, 09:29 | #3 | 
| Участник | 
			
			Интересно, а какой, по вашему, запрос должен сформироваться?
		 
				__________________ Axapta v.3.0 sp5 kr2 | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  22.06.2007, 09:40 | #4 | 
| Member | 
			
			Уровень кэширования на таблице RAssetTable у вас стандартный? Это не экземпляр временной таблицы? Запросы всегда разбиваются, если в них включена таблица с уровнем кэширования EntireTable или временная таблица.
		 
				__________________ С уважением, glibs® | 
|  | |
| За это сообщение автора поблагодарили: zemlyn (1), kashperuk (5), Мариночка (2), 3oppo (1). | |
|  22.06.2007, 11:02 | #5 | 
| Участник | 
			
			Да пробовал убирать firstonly без результатно!    X++: while select RPayJournalTable where RPayJournalTable.JournalId == 'ЗП000628' join RPayJournalTrans where RPayJournalTrans.JournalId == RPayJournalTable.JournalId join RPayTrans where RPayTrans.SourceRecId == RPayJournalTrans.RecId { i++; } box::info( int2str(i) ); to AndyD ну уж никак не из 4000 селектов! RAssetTable стандартно не каких временных таблиц! 
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  22.06.2007, 18:04 | #6 | 
| Участник | 
			
			Насколько я понял firstonly  в join-ах вообще игнорируются. У меня тоже как то получалось что join разбивал select но я так и не разобрался в чём там дело. Просто используй «прямой запрос» к базе, сам так делал. Выигрыш в скорости в РАЗЫ!!
		 | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  22.06.2007, 21:58 | #7 | 
| Участник | Цитата: Прямой запрос в разы сложнее отлаживать и в разы дороже в сопровождении. Прежде чем следовать совету МРАКОбеса триджы подумайте. | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  25.06.2007, 08:38 | #8 | 
| Участник | 
			
			Не совсем понял о чём речь? Согласен! А что делать?! Если разница в скорости в 50 раз!!! 
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  25.06.2007, 09:06 | #9 | 
| Участник | 
			
			Нисколько не сомневаюсь, что не поняли. Но тем не менее категорично советуете.  для начала назову пару вещей: виртуальные компани, rls. про autorelation, временные таблицы, вычисляемые поля, про енумы, про целостность, про переопределенные методы при чтении/вставке/записи/удалении и т.п. уж как-нибудь сами. в общем, rtfm. Во-первых, грамотно использовать втроенные средства. Во-вторых, прекратите мерить разницу в монопольном режиме. Хоть раз померяйте при нормальной загрузке sql-сервера с нормальным числом пользователей. Замерьте наконец задержки, которые происходят у других пользователей из-за ваших прямых запросов. Барабашки нет.   | 
|  | 
|  25.06.2007, 09:34 | #10 | 
| Модератор | Цитата: Как только вижу в коде прямое обращние к базе, это с 99% вероятностью означает, что барабашка скоро появится. С Уважением, Георгий | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  25.06.2007, 09:45 | #11 | 
| Участник | 
			
			  ?????    Цитата: Научите плиз!? Вдруг чего не знаю. Цитата: Цитата: Судя по оставшемуся главному вопросу, он всё таки есть!   
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  22.06.2007, 18:09 | #12 | 
| Участник | 
			
			А вы. Не пробовали использовать стандартные Query?! Он вроде как быстрее должен работать!
		 | 
|  | 
|  22.06.2007, 18:36 | #13 | 
| Member | 
			
			Попробовал написать джоб похожий (на стандартной функциональности только). Select один при декларировании курсора. Дольше идут вызовы управления курсором. Либо вы чего-то не договариваете... А какой вид у вас имеют все 4837 запроса? Они абсолютно одинаковы? Может у вас сам метод столько раз вызывается? Тогда не удивлюсь насчет 25 мин. 
				__________________ С уважением, glibs® | 
|  | 
|  25.06.2007, 08:32 | #14 | 
| Участник | Цитата: Вот метод полностью: X++: protected Map initRasset01Map() { Map _ret = new Map(Types::String, Types::Date); Set _account01Set = this.initAccount01Set(); RAssetTable _rassetTable; RAssetTrans _rassetTrans; LedgerTrans _ledgerTrans; int i, ip4, ip2, ip3; while select _rassetTable index RAssetNumIdx where _rassetTable.VGP_PropertyTax == NoYes::Yes join firstonly _rassetTrans index TransTypeIdx where _rassetTrans.AccountNum == _rassetTable.AccountNum && _rassetTrans.AssetTransType == RAssetTransType::Acquisition && _rassetTrans.TransDate <= reportDateEnd join firstonly _ledgerTrans index VGP_LedgerLinkIdx where _ledgerTrans.VGP_LedgerLinkId == _rassetTrans.VGP_LedgerLinkId && _ledgerTrans.VGP_LedgerLinkModuleRef == VGP_LedgerLinkModuleRef::RAsset && //ОС _ledgerTrans.Voucher == _rassetTrans.Voucher && _ledgerTrans.TransDate == _rassetTrans.TransDate { i++; if (_account01Set.in(_ledgerTrans.AccountNum)) { _ret.insert(_rassetTable.AccountNum, this.getDisposalDate(_rassetTable.AccountNum)); } } // box::info( int2str(i) ); return _ret; } Переписал на прямой запрос в той же функции, выполняется вместо 26 минут - 30 секунд. Посмотрел генерируемые запросы, вроде одинаковые вот такого вида: SELECT A.TRANSDATE,A.RECID,A.VGP_LEDGERLINKID FROM RASSETTRANS A(INDEX(I_16077RASSETDATEIDX)) WHERE ((DATAAREAID=?) AND (((ACCOUNTNUM=?) AND (TRANSDATE<?)) AND ((((ASSETTRANSTYPE=?) OR (ASSETTRANSTYPE=?)) OR (ASSETTRANSTYPE=?)) OR (ASSETTRANSTYPE=?)))) OPTION(FAST 2) внутри проскакивают 2-3 другого вида но непонятно к чему они относятся. Цитата:       
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  25.06.2007, 09:25 | #15 | 
| Участник | Цитата: 
		
			Сообщение от 3oppo
			   Вот метод полностью: ... Посмотрел генерируемые запросы, вроде одинаковые вот такого вида: SELECT A.TRANSDATE,A.RECID,A.VGP_LEDGERLINKID FROM RASSETTRANS A(INDEX(I_16077RASSETDATEIDX)) WHERE ((DATAAREAID=?) AND (((ACCOUNTNUM=?) AND (TRANSDATE<?)) AND ((((ASSETTRANSTYPE=?) OR (ASSETTRANSTYPE=?)) OR (ASSETTRANSTYPE=?)) OR (ASSETTRANSTYPE=?)))) OPTION(FAST 2) внутри проскакивают 2-3 другого вида но непонятно к чему они относятся. Здесь идет связка по OR для нескольких условий для ASSETTRANSTYPE, а в коде x++ - по одному. Попробуйте оставить только выборку и цикл по ней и посмотрите на результат запроса. 
				__________________ Axapta v.3.0 sp5 kr2 | 
|  | 
|  25.06.2007, 09:53 | #16 | 
| Участник | 
			
			Пробовал коментарить код внутри цикла, на времени выполнения это не отразилось.
		 
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  25.06.2007, 13:51 | #17 | 
| Member | Цитата: Включите мониторинг длинных запросов. Посмотрите, действительно ли этот злополучный запрос так долго отрабатывает именно в Аксапте. Запустите профайлер кода, в конце концов. Убедитесь, что время уходит именно на запрос. 
				__________________ С уважением, glibs® | 
|  | 
|  25.06.2007, 14:30 | #18 | 
| Участник | 
			
			На количестве запросов отразилось, я же написал запрос всё таки один. (Там хитро запускался простой select) Но выполняется очень медленно. С простым инкрементом вместо кода. Цитата: Что есть время выполнения запроса?! Это время до выхода из полного цикла, или это время до попадания внутрь цикла? Обратил внимание на такую вещь: При АКСАПТАВСКОМ запросе, попадание внутрь цикла происходит быстро ( 5 сек), НО само прохождение по циклу идёт очень медленно, хотя внутри выполняется только i++; При прямом запросе, и попадение внутрь цикла и сам цикл (с кодом i++) делаются очень быстро. Может это как то, кому то, прояснит ситуацию!? 
				__________________ PS. Сложно приехать в Москву, но ещё сложнее уехать отсюда. | 
|  | 
|  25.06.2007, 10:06 | #19 | 
| Участник | 
			
			Еще можно включить трассировку SQL и походить по шагам внимательно глядя в список infolog дебаггера. И посмотреть какая строка генерирует приведенный SQL. Еще можно трассировать SQL в файл и посмотреть по стеку какая строчка его генерит. | 
|  | |
| За это сообщение автора поблагодарили: 3oppo (1). | |
|  25.06.2007, 10:14 | #20 | 
| Модератор | 
			
			не проверял с клиентом SP3, но все же  - какой глубокий смысл заложен в X++: join firstonly RAssetTrans X++: join firstonly LedgerTrans - с какой целью используются X++: index RAssetNumIdx index TransTypeIdx index VGP_LedgerLinkIdx 
				__________________ -ТСЯ или -ТЬСЯ ? | 
|  | 
| Теги | 
| производительность, запрос (query), ax3.0 | 
|  | 
| 
 |