Показать сообщение отдельно
Старый 18.09.2005, 22:51   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2494 (89) +++++++++
Регистрация: 20.08.2005
Все нижеследующее имеет отношение только к работе с MS SQL Server

Давайте сначала определимся, что делает FAST
Цитата:
SQL Server Books Online
Specifies that the query is optimized for fast retrieval of the first number_rows (a nonnegative integer). After the first number_rows are returned, the query continues execution and produces its full result set.
Если в запросе присутствует этот хинт, то при получении первых n записей сервер вернет их клиенту и после этого продолжит выполнять запрос до получения оставшихся. Вот и все. Никаких ускорений и никаких замедлений. Предназначение хинта - отзывчивость приложения, т.е. клиент получит первые записи с максимальной скоростью, а затем будет ждать получения оставшихся.

В чем заключается оптимизация? Рассмотрим на примере InventTable (планы выполнения - во вложении).
PHP код:
select recid from InventTable order by dataareaiditemgroupid 
Что будет, если отослать этот запрос на сервер? Какой план запроса будет выбран?
Будет выбран кластерный индекс I_175ITEMIDX. Оптимизатор решил, что выбрать записи по нему, а затем отсортировать на сервере будет быстрее, чем использовать индекс по полям, учавствующим в сортировке. Но в этом случае для получения первой записи на клиенте необходимо получить все записи таблицы, отсортировать их и только после этого клиент получит то что запросил. При большом количестве записей ожидание выполнения запроса может занять десятки секунд.
PHP код:
select recid from InventTable order by dataareaiditemgroupid option (fast 10
Добавим хинт FAST. Теперь план исполнения изменился. Используется индекс по полям, участвующим в предложении ORDER BY (I_175GROUPITEMIDX). Первые записи могут быть получены сразу. На клиента отправляется 10 записей, а затем сервер, так же как и в первом случае, продолжает поиск записей, удовлетворяющих условию. Первые записи могут быть получены сразу, но общее время выполнения запроса может увеличиться.

В общем виде использование хинта FAST ведет вот к чему. Если существует индекс по полям, входящим в предложение ORDER BY, то будет использоваться этот индекс и мы получим первые записи насколько возможно быстро. Если нет, то будет использоваться индекс выбранный оптимизатором, а сортировка будет произведена на сервере. Получение записей будем ждать, пока запрос не будет выполнен полностью.

Так как Axapta использует хинт FAST во всех запросах, то, получается, что ORDER BY является недокументированной возможностью повлиять на выполнение запроса (по крайней мере мне не встречалась информация по этому поводу). А так же возможностью затормозить выполнение запроса по самое не балуйся.


Перейдем к рассмотрению работы самой Axapta'ы с SQL сервером.

А работает она с использованием семейства функций sp_cursor* jtds.sourceforge.net/apiCursors.html. При выполнении любого запроса (в том числе и используемого в DataSource) Axapta открывает на сервере курсор (курсор имеет тип Fast forward-only cursor). При этом может использоваться подготовка (prepare) запроса для дальнейшего многократного использования. Каждая функция принимает в качестве параметров тип курсора, вид блокировки и сам запрос (или его хэндл для prepared запросов). Функция открывает курсор, отдает запрос серверу и ожидает его выполнения. После получения ответа от сервера клиенту возвращается хэндл курсора. Дальше Axapta начинает фетчить записи на клиента (sp_cursorfetch). Записи, в основном, фетчатся группами (для ускорения выборки). После окончания обработки происходит закрытие курсора (sp_cursorclose), а так же для prepared запросов возможен вызов sp_cursorunprepare если необходимость в нем отпала.
У этого семейства функций есть одна осбенность, которая помогает Axapta'е минимизировать простои при выполнении запросов - все они возвращают управление в тот момент, когда вернет управление сервер. Т.е. при использовании хинта FAST мы получим хэндл курсора сразу после получения первых записей (тут необходимо учитывать то, что написано выше про FAST, т.е. могут быть запросы, которые в любом случае будут выполнены полностью). Дальнейшее продолжение запроса выполняется при фетче записей, причем каждый раз возвращается столько, сколько нам необходимо.

Теперь вернемся к предмету разговора - совместному использованию firstonly и firstfast.
Само выполнение запроса не ведет к возврату записей на клиента, т.е. даже не смотря на то, что при использовании firstfast в запросе передается FAST 1, получим эти записи мы лишь при фетче - сервер выберет 1 уже уже найденную запись и продолжит поиск остальных записей группы. Т.е. реально время, потраченное на поиск и выборку записей будет и в том и в другом случае одинаковым.
Тут может возникнуть такое соображение - хорошо, но в случае открытия на обновление могут возникнуть блокировки и даже разница в одну запись может оказаться существенной. Но в данном случае Axapta ведет себя несколько иначе - при использовании хинта firstonly в запрос добавляется FAST 1, а на клиента фетчится 1 запись.

Таким образом добавление firstfast в запрос с firstonly ничего не добавляет в плане производительности.

Использование firstfast отдельно имеет смысл только при открытии запроса на обновление, т.к. в этом случае при большой нагрузке на сервер возможен временной интервал м-ду открытием запроса (с одной записью) и фетчем записей на клиента (группы записей)


2 moderators
Если это интересно, то я мог бы разместить более расширенную информацию по работе Axapta с сервером. Укажите в каком разделе. Приношу извинения, если этот вопрос надо было задавать не в этом сообщении
Миниатюры
Нажмите на изображение для увеличения
Название: inventtableplans.jpg
Просмотров: 607
Размер:	66.5 Кб
ID:	710  
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: Garic (1), blokva (1), Recoilme (3), Logger (7), wojzeh (1).