24.12.2020, 09:04 | #1 |
Участник
|
AX2009 и FETCH API_CURSOR
Друзья, у меня появились вопросы по FETCH API_CURSOR.
Есть некий запрос, допустим: X++: while select ledgerTrans index hint ACDate where ledgerTrans.AccountNum == "AccountNum" && ledgerTrans.TransDate <= 29\02\2020 && ledgerTrans.Posting == LedgerPostingType::LedgerJournal { /*что-то там написано*/ } Запрос в SQL выполняется быстро, первую десятку прогонов в цикле тоже быстро, НО потом на каком-то курсоре может зависнуть на десятки минут. При этом местный ДБА говорит, что за FETCH API_CURSOR* скрывается некий запрос который SQL пытается выполнить. Это так? Я всегда думал, что логично сначала выкачать данные, а потом просто по ним пробежаться. Зачем тогда выполнять мелкие под запросы в БД, какой в этом смысле? Может уже ДБА несет ересь? Кто-то сталкивался с таким поведением FETCH API_CURSOR? Как-то это лечится?
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 10:44 | #2 |
Участник
|
Да, это выборка данных при помощи открытого курсора. Как понимаю, выбора идет порционно по мере возможности как выдачи данных SQL, так и получения потребителем.
В момент выполнения можно (зная номер сессии) даже увидеть что за запрос там в основе лежит, а не только считать его "неким": Код: SELECT curs.session_id, curs.properties, curs.creation_time, curs.is_open, sqlSttm.text FROM sys.dm_exec_cursors 123 curs CROSS APPLY sys.dm_exec_sql_text (curs.sql_handle) sqlSttm |
|
|
За это сообщение автора поблагодарили: mazzy (2), Vadik (1), AlexeyS (3), Logger (3). |
24.12.2020, 10:58 | #3 |
Участник
|
Цитата:
Сообщение от Raven Melancholic
Да, это выборка данных при помощи открытого курсора. Как понимаю, выбора идет порционно по мере возможности как выдачи данных SQL, так и получения потребителем.
В момент выполнения можно (зная номер сессии) даже увидеть что за запрос там в основе лежит, а не только считать его "неким": Код: SELECT curs.session_id, curs.properties, curs.creation_time, curs.is_open, sqlSttm.text FROM sys.dm_exec_cursors 123 curs CROSS APPLY sys.dm_exec_sql_text (curs.sql_handle) sqlSttm
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 11:29 | #4 |
Участник
|
Нет.
Правильная формулировка: Первую порцию данных SQL возвращает быстро. Потом готовит остальные порции во время "готовки" SQL выполняет и другие запросы. в том числе и такие, которые захватили какие-то проводки в этой таблице на запись (forupdate). тогда "готовка" терпеливо ждет освобождения блокировок. |
|
24.12.2020, 11:34 | #5 |
Участник
|
Цитата:
https://github.com/TrudAX/TRUDScript...ait-statistics Чего конкретно ждет один определенный курсор посмотреть вряд ли получится, по запросу можно посмотреть план, если он простой, но наверное можно прикинуть что он может примерно ждать, однако надо представлять что за данные ему передаются |
|
|
За это сообщение автора поблагодарили: AlexeyS (3). |
24.12.2020, 11:44 | #6 |
Участник
|
В данном конкретном случае наверное таки можно.
запрос по финансовым проводкам. скорее всего кто-то в соседней сессии усердно делает разноску в ГК. (может быть даже в соседнем методе этой сессии). (может быть даже в период до 29\02\2020). делает настолько усердно, что SQL эскалировал блокировки до страниц. в ax2009 по умолчанию кластерный индекс в таблице LedgerTrans установлен по RecID... если была разноска "задним числом", то страницы с данными могут быть перемешаны как угодно. ========== мне кажется, что основная проблема была в модели, которая была у автора в голове. автор считал, что SQL сначала получает все данные, а потом передает их. в данном случае нет никаких команд на агрегирование/сортировку поэтому SQL будет передавать по мере готовности. следовательно, проблема не в Fetch, просто где-то обычная блокировка. |
|
24.12.2020, 11:49 | #7 |
Участник
|
Чтение вроде не должно ничем блокироваться в 2009. С этой версии используется snapshot isolation
|
|
24.12.2020, 11:54 | #8 |
Участник
|
не должно. согласен.
должна использоваться, хочешь сказать согласен, должна. однако автор наблюдает следующее поведение "потом на каком-то курсоре может зависнуть на десятки минут". я бы поставил на то, что таки где-то что-то заблокировано, и поискал бы блокировки до того, как копать в сторону fetch и буферов. |
|
24.12.2020, 11:58 | #9 |
Участник
|
Дополню, что если запрос выполнить на SQL. Без участия аксапты, то выдает все данные быстро.
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 12:02 | #10 |
Участник
|
Почему сразу заблокировано. Может быть просто перебор Nested loop в плане. Т.е. к примеру для счета перебираются проводки определенных типов, сначала они есть нужные, дальше идет к примеру куча проводок где нужных типов нет (но чтобы это узнать - их надо все прочитать, в этот момент и будет зависание)
Надо создать индекс AccountNum, Posting, TransDate, тогда выбираться будет только то что нужно |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
24.12.2020, 12:04 | #11 |
Участник
|
Цитата:
стопудов в Аксапте вы выполняете процесс который в одной сессии пытается и записать в LedgerTrans и прочитать из этой же таблицы типа в одном цикле пытается "получить сальдо" по счету на дату и разнести какую-нибудь коррекцию на этот же счет. точно никто не вызывал метод selectForUpdate(true) на таблице, которая участвует в читающем запросе, который вы привели в первом посте? Последний раз редактировалось mazzy; 24.12.2020 в 12:07. |
|
24.12.2020, 12:05 | #12 |
Участник
|
|
|
24.12.2020, 12:58 | #13 |
Боец
|
А что там у вас за индекс ACDate - какие поля в нём?
Попробуйте убрать hint для начала + На всякий случай: где у вас код ранится, не на клиенте часом? Последний раз редактировалось DSPIC; 24.12.2020 в 13:22. |
|
24.12.2020, 13:11 | #14 |
Участник
|
Цитата:
Сообщение от mazzy
Какая нехорошая девочка! Не получит подарки на новый год. И корпоратив проводите "Без участия аксапты"
стопудов в Аксапте вы выполняете процесс который в одной сессии пытается и записать в LedgerTrans и прочитать из этой же таблицы типа в одном цикле пытается "получить сальдо" по счету на дату и разнести какую-нибудь коррекцию на этот же счет. точно никто не вызывал метод selectForUpdate(true) на таблице, которая участвует в читающем запросе, который вы привели в первом посте? Не помог forceliterals.
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 13:20 | #15 |
Участник
|
Цитата:
AccountNum TransDate Voucher AmountMST Убрал хинт, результат тот-же
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 13:23 | #16 |
Участник
|
Я правильно понимаю, что проблема в считывании данных из выборки? Т.е. axapta у SQL забирает данные порционно. Т.к. некоторая порция может задерживаться, то и fetch выдает зависание. Чтобы это победить, все поля в выборке должны быть по индексу?
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег. |
|
24.12.2020, 16:12 | #17 |
Участник
|
Из описания не очень понятно какую проблему вы пытаетесь решить. Если это анализ общей загрузки сервера, то это один подход, вы анализируете топ запросы, процент ожиданий и т.д(https://denistrunin.com/performance-audit). Если это долгое время работы конкретной операции - вам надо делать тестовый пример и прогонять его в трейс парсере, искать что там занимает больше всего времени
|
|
24.12.2020, 18:13 | #18 |
Участник
|
Цитата:
Физически, Aхapta всегда оборачивает запрос в курсор-SQL, а план выполнения для курсора может принципиально отличаться от плана выполнения для запроса Т.е. для целей тестирования именно производительности запроса в SQL надо делать так X++: DECLARE test CURSOR FOR select * from ledgerTrans with (index (ACDate)) //Имя индекса будет другое where ledgerTrans.dataAreaId = 'dat' // Если есть dataAreaId and ledgerTrans.AccountNum = "AccountNum" and ledgerTrans.TransDate <= '20200229' and ledgerTrans.Posting = 14 --LedgerPostingType::LedgerJournal open test // Тормоза ожидаются вот здесь FETCH NEXT FROM test //Перебор записей WHILE @@FETCH_STATUS = 0 begin FETCH NEXT FROM test end CLOSE test DEALLOCATE test Правда обычно тормоза бывают на самом первом шаге. На самом первом FETCH. Дальше обычно все быстро идет. Если же тормоза наблюдаются в процессе перебора записей, то попробуйте для начала перестроить индексы...
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: trud (2). |
24.12.2020, 20:26 | #19 |
Участник
|
Ну а если уж совсем приближенно к Аксапте делать, то еще и можно воспользоваться процедурами sp_cursor*
Но анализировать что там получается это та еще задачка. |
|
25.12.2020, 13:43 | #20 |
Участник
|
Дима, привет) Задай какую-нибудь сортировку не по индексу в выборке. Тогда твоя выборка целиком сначала уйдет в TempDB и по идее дальше ничего не должно мешать получению данных из нее. Да на первом шаге ты получишь некоторое подвисание. Зато дальше не должно быть проблем. Понимаю, что это не отвечает на вопрос почему, но проблему на мой взгляд должно решить.
|
|
|
За это сообщение автора поблагодарили: demianimp (2). |
Теги |
ax2009, fetch api_cursor, sql server |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|