AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 24.12.2020, 09:04   #1  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
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 в AX (возможно ересь написал).
Запрос в SQL выполняется быстро, первую десятку прогонов в цикле тоже быстро, НО потом на каком-то курсоре может зависнуть на десятки минут. При этом местный ДБА говорит, что за FETCH API_CURSOR* скрывается некий запрос который SQL пытается выполнить. Это так? Я всегда думал, что логично сначала выкачать данные, а потом просто по ним пробежаться. Зачем тогда выполнять мелкие под запросы в БД, какой в этом смысле? Может уже ДБА несет ересь?

Кто-то сталкивался с таким поведением FETCH API_CURSOR? Как-то это лечится?
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 10:44   #2  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,164 / 1293 (48) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Да, это выборка данных при помощи открытого курсора. Как понимаю, выбора идет порционно по мере возможности как выдачи данных 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
Где 123 это номер сессии
За это сообщение автора поблагодарили: mazzy (2), Vadik (1), AlexeyS (3), Logger (3).
Старый 24.12.2020, 10:58   #3  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от 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
Где 123 это номер сессии
Спасибо, с запросом понятно как вытащить. Вопрос, что может мешать считыванию?
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 11:29   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от demianimp Посмотреть сообщение
Запрос в SQL выполняется быстро
Нет.
Правильная формулировка:
Первую порцию данных SQL возвращает быстро. Потом готовит остальные порции

во время "готовки" SQL выполняет и другие запросы.
в том числе и такие, которые захватили какие-то проводки в этой таблице на запись (forupdate).

тогда "готовка" терпеливо ждет освобождения блокировок.
__________________
полезное на axForum, github, vk, coub.
Старый 24.12.2020, 11:34   #5  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от demianimp Посмотреть сообщение
Спасибо, с запросом понятно как вытащить. Вопрос, что может мешать считыванию?
Вы можете просмотреть текущие ожидания SQL подобным запросом
https://github.com/TrudAX/TRUDScript...ait-statistics
Чего конкретно ждет один определенный курсор посмотреть вряд ли получится, по запросу можно посмотреть план, если он простой, но наверное можно прикинуть что он может примерно ждать, однако надо представлять что за данные ему передаются
За это сообщение автора поблагодарили: AlexeyS (3).
Старый 24.12.2020, 11:44   #6  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от demianimp Посмотреть сообщение
Есть некий запрос, допустим:
X++:
while select ledgerTrans
Цитата:
Сообщение от trud Посмотреть сообщение
Чего конкретно ждет один определенный курсор посмотреть вряд ли получится
В данном конкретном случае наверное таки можно.
запрос по финансовым проводкам.

скорее всего кто-то в соседней сессии усердно делает разноску в ГК.
(может быть даже в соседнем методе этой сессии).
(может быть даже в период до 29\02\2020).
делает настолько усердно, что SQL эскалировал блокировки до страниц.

в ax2009 по умолчанию кластерный индекс в таблице LedgerTrans установлен по RecID... если была разноска "задним числом", то страницы с данными могут быть перемешаны как угодно.

==========
мне кажется, что основная проблема была в модели, которая была у автора в голове.
автор считал, что SQL сначала получает все данные, а потом передает их.
в данном случае нет никаких команд на агрегирование/сортировку
поэтому SQL будет передавать по мере готовности.

следовательно, проблема не в Fetch, просто где-то обычная блокировка.
__________________
полезное на axForum, github, vk, coub.
Старый 24.12.2020, 11:49   #7  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Чтение вроде не должно ничем блокироваться в 2009. С этой версии используется snapshot isolation
Старый 24.12.2020, 11:54   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от trud Посмотреть сообщение
Чтение вроде не должно ничем блокироваться в 2009.
не должно. согласен.

Цитата:
Сообщение от trud Посмотреть сообщение
С этой версии используется snapshot isolation
должна использоваться, хочешь сказать
согласен, должна.

однако автор наблюдает следующее поведение "потом на каком-то курсоре может зависнуть на десятки минут".

я бы поставил на то, что таки где-то что-то заблокировано,
и поискал бы блокировки до того, как копать в сторону fetch и буферов.
__________________
полезное на axForum, github, vk, coub.
Старый 24.12.2020, 11:58   #9  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Дополню, что если запрос выполнить на SQL. Без участия аксапты, то выдает все данные быстро.
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 12:02   #10  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Почему сразу заблокировано. Может быть просто перебор Nested loop в плане. Т.е. к примеру для счета перебираются проводки определенных типов, сначала они есть нужные, дальше идет к примеру куча проводок где нужных типов нет (но чтобы это узнать - их надо все прочитать, в этот момент и будет зависание)
Надо создать индекс AccountNum, Posting, TransDate, тогда выбираться будет только то что нужно
За это сообщение автора поблагодарили: mazzy (2).
Старый 24.12.2020, 12:04   #11  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от demianimp Посмотреть сообщение
Дополню, что если запрос выполнить на SQL. Без участия аксапты, то выдает все данные быстро.
Какая нехорошая девочка! Не получит подарки на новый год. И корпоратив проводите "Без участия аксапты"

стопудов в Аксапте вы выполняете процесс который в одной сессии пытается и записать в LedgerTrans и прочитать из этой же таблицы

типа в одном цикле пытается "получить сальдо" по счету на дату и разнести какую-нибудь коррекцию на этот же счет.
точно никто не вызывал метод selectForUpdate(true) на таблице, которая участвует в читающем запросе, который вы привели в первом посте?
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 24.12.2020 в 12:07.
Старый 24.12.2020, 12:05   #12  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от demianimp Посмотреть сообщение
Дополню, что если запрос выполнить на SQL. Без участия аксапты, то выдает все данные быстро.
О.. тогда у вас скорее всего проблема parameters sniffing. Поставьте хинт forceliterals в запрос, тогда должно быть одинаково. Ну или индекс
Старый 24.12.2020, 12:58   #13  
DSPIC is offline
DSPIC
Боец
 
1,077 / 1243 (44) ++++++++
Регистрация: 11.04.2008
А что там у вас за индекс ACDate - какие поля в нём?
Попробуйте убрать hint для начала

+ На всякий случай: где у вас код ранится, не на клиенте часом?

Последний раз редактировалось DSPIC; 24.12.2020 в 13:22.
Старый 24.12.2020, 13:11   #14  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от mazzy Посмотреть сообщение
Какая нехорошая девочка! Не получит подарки на новый год. И корпоратив проводите "Без участия аксапты"

стопудов в Аксапте вы выполняете процесс который в одной сессии пытается и записать в LedgerTrans и прочитать из этой же таблицы

типа в одном цикле пытается "получить сальдо" по счету на дату и разнести какую-нибудь коррекцию на этот же счет.
точно никто не вызывал метод selectForUpdate(true) на таблице, которая участвует в читающем запросе, который вы привели в первом посте?
Нет, в джобе только select (вывод данных в файл для анализа)

Цитата:
Сообщение от trud Посмотреть сообщение
О.. тогда у вас скорее всего проблема parameters sniffing. Поставьте хинт forceliterals в запрос, тогда должно быть одинаково. Ну или индекс
Не помог forceliterals.
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 13:20   #15  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Цитата:
Сообщение от DSPIC Посмотреть сообщение
А что там у вас за индекс ACDate - какие поля в нём?
Попробуйье убрать hint для начала
\Data Dictionary\Tables\LedgerTrans\Indexes\ACDate\
AccountNum
TransDate
Voucher
AmountMST

Убрал хинт, результат тот-же
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 13:23   #16  
demianimp is offline
demianimp
Участник
 
202 / 104 (4) +++++
Регистрация: 10.10.2013
Я правильно понимаю, что проблема в считывании данных из выборки? Т.е. axapta у SQL забирает данные порционно. Т.к. некоторая порция может задерживаться, то и fetch выдает зависание. Чтобы это победить, все поля в выборке должны быть по индексу?
__________________
Любую техническую проблему можно решить, если есть достаточно времени и денег.
Старый 24.12.2020, 16:12   #17  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,039 / 1630 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Из описания не очень понятно какую проблему вы пытаетесь решить. Если это анализ общей загрузки сервера, то это один подход, вы анализируете топ запросы, процент ожиданий и т.д(https://denistrunin.com/performance-audit). Если это долгое время работы конкретной операции - вам надо делать тестовый пример и прогонять его в трейс парсере, искать что там занимает больше всего времени
Старый 24.12.2020, 18:13   #18  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от demianimp Посмотреть сообщение
Дополню, что если запрос выполнить на SQL. Без участия аксапты, то выдает все данные быстро.
Вы неправильно их готовите

Физически, 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  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,164 / 1293 (48) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Ну а если уж совсем приближенно к Аксапте делать, то еще и можно воспользоваться процедурами sp_cursor*
Но анализировать что там получается это та еще задачка.
Старый 25.12.2020, 13:43   #20  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Дима, привет) Задай какую-нибудь сортировку не по индексу в выборке. Тогда твоя выборка целиком сначала уйдет в TempDB и по идее дальше ничего не должно мешать получению данных из нее. Да на первом шаге ты получишь некоторое подвисание. Зато дальше не должно быть проблем. Понимаю, что это не отвечает на вопрос почему, но проблему на мой взгляд должно решить.
За это сообщение автора поблагодарили: demianimp (2).
Теги
ax2009, fetch api_cursor, sql server

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
sertandev: Empowering D365 FO service endpoints with Azure API Management service Blog bot DAX Blogs 0 15.05.2019 22:11
dynamicsnavax: Hybrid connection - Web Api App for AX 2012 to Azure-part 4 Blog bot DAX Blogs 0 14.09.2017 13:11
gideonvos: API to CDM using Flow in a PowerApp Blog bot DAX Blogs 0 08.09.2017 11:11
goshoom: Open API for JSON-based custom services in AX 7 Blog bot DAX Blogs 0 22.07.2017 14:17
axinthefield: Choosing a Single Deployment or Multiple Deployments of AX2009 Blog bot DAX Blogs 0 15.06.2011 03:25

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 22:22.