|
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 |
|
|