AXForum  
Zurück   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Kennwort vergessen?
Registrieren Forum Rules Hilfe Benutzerliste Heutige Beiträge Suchen

 
 
Themen-Optionen Thema durchsuchen Ansicht
Alt 28.01.2004, 15:29   #1  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
? Почему такое расхождение в скорости выполнения
Я не понимаю механизм доступа к данным в Axapta 2.5 Сделал простенький тест

PHP-Code:
static void Job_test(Args _args)
{
    
Connection      Con = new Connection();
    
Statement       Stmt Con.createStatement();
    
ResultSet       R;
    
CommaIo         fileOut;
    
int             timenowBegini;
    
InventTable     inventTable;

;

    
// Формирование ResultSet
    
fileOut = new CommaIo("C:\test_con.txt","W");
    
timenowBegin=timenow();
    
Stmt.executeQuery('SELECT TOP 1000 * FROM InventTable');

    while ( 
R.next() )
    {
        
fileOut.write(R.getString(1),
                        
R.getString(2),
                        
R.getString(3),
                        
R.getString(4),
                        
R.getString(5),
                        
R.getString(6),
                        
R.getString(7),
                        
R.getString(8),
                        
R.getString(9),
                        
R.getString(10),
                        
R.getString(11),
                        
R.getString(12),
                        
R.getString(13),
                        
R.getString(14),
                        
R.getString(15),
                        
R.getString(16),
                        
R.getString(17),
                        
R.getString(18),
                        
R.getString(19),
                        
R.getString(20) );
    }
    
info("Время сброса ResultSet = "+int2str(timenow()-timenowBegin));
    
Stmt.close();

    
// Чтение из табличной переменной
    
fileOut = new CommaIo("C:\test_sel.txt","W");
    
0;
    
timenowBegin=timenow();

    
select from inventTable;

    while (
i<=1000)
    {
        
i++;
        
next inventTable;
        
fileOut.write(inventTable.ItemGroupID,
                        
inventTable.ItemID,
                        
inventTable.ItemName,
                        
inventTable.ItemType,
                        
inventTable.PURCHMODEL,
                        
inventTable.HEIGHT,
                        
inventTable.WIDTH,
                        
inventTable.SALESMODEL,
                        
inventTable.COSTGROUPID,
                        
inventTable.REQGROUPID,
                        
inventTable.PRIMARYVENDORID,
                        
inventTable.NETWEIGHT,
                        
inventTable.DEPTH,
                        
inventTable.UNITVOLUME,
                        
inventTable.BOMUNITID,
                        
inventTable.DENSITY,
                        
inventTable.SCRAPTYPEID,
                        
inventTable.DIMENSION[1],
                        
inventTable.DIMENSION[2],
                        
inventTable.DIMENSION[3] );
    }
    
info("Время сброса прямого сканирования = "+int2str(timenow()-timenowBegin));

Получил расхождение в скорости примерно на порядок (если увеличить число выбрасываемых полей или количество строк это будет заметнее). Т.е. выброс в текстовый файл из ResulSet примерно на порядок МЕДЛЕННЕЕ, чем тот же выброс из табличной переменной. Почему собственно?

Собственно, изначально вопрос возник в попытке ускорить выброс результата выборки в текстовый файл. Выполнение Query с последующим циклом оказалось сопоставимо по времени с выбросом из ResulSet (примерно одинаково). Т.е. наиболее оптимальным по скорости оказалась такая технология:

-) Создать таблицу на сервере
-) Выполнить хранимую процедуру сервера по наполнению этой таблицы
-) Средствами Axapta сделать выброс из этой таблицы в текстовый файл

Но это достаточно сложно по исполнению, поэтому не хотелось бы этого делать.

Меня интересует, почему есть такое явное расхождение в скорости обработки казалось бы одинаковых операций?
Alt 28.01.2004, 15:51   #2  
andreynikolai ist offline
andreynikolai
Участник
 
133 / 10 (1) +
Registriert seit: 11.04.2002
А что здесь удивительного ?

При использовании класса UserConnection вы же фактически
напрямую обращаетесь к SQL-Server.

Ведь Аксапта - это же по сути скрипт.

Ваш код написанный на X++ должен пройти всю цепочку обработки бизнес-логики, компиляции,
преобразований прежде чем запрос уйдет к SQL-серверу.
Alt 28.01.2004, 15:57   #3  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Это Вы о чем?

Результат запроса я уже получил. Расхождение в скорости имеет место быть именно в цикле while. Т.е. это не собственно выполнение запроса, а выборка информации из результирующей выборки. Какое отношение ко всему этому имеет бизнес-логика и компиляция? Или компилируется каждая строка отдельно по мере исполнения?
Alt 28.01.2004, 16:10   #4  
macklakov ist offline
macklakov
NavAx
Benutzerbild von macklakov
 
2.347 / 996 (38) +++++++
Registriert seit: 03.04.2002
Zitat:
Изначально опубликовано Владимир Максимов
уже получил
Не правда, select-ы стоят между timenow(). Скорее всего, ускорение достигается за счет кэширования, какая у вас конфигурация(2 или 3- tier) и настройки cacheLookup? Попробуй тот-же тест на более сложных запросах, по нескольким таблицам, результат должен отличаться в обратную сторону
P.S. next обычно ставят в конце while, т.к. select на автомате дает первую запись
Alt 28.01.2004, 16:30   #5  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Думаете - это первый вариант? Это упрощение моего оригинального запроса, где связаны 4 таблицы по INNER JOIN, да еще несколько промежуточных вычислений внутри цикла.

Я же писал, что тормозит именно цикл while. Все что вне него - это разовые операции принципиального влияния на общее время выполнения не оказывают

Хорошо, переставил timenowBegin = timenow() после select и R=... Перекинул next в конец цикла. На результат это никак не повлияло!

У меня 3-х звенка. Где здесь предмет кэширования я не понимаю. Точнее, если есть кэширование для табличной переменной, то почему его нет для ResultSet или Query?
Alt 28.01.2004, 16:54   #6  
france ist offline
france
Участник
 
159 / 11 (1) +
Registriert seit: 24.11.2003
Ort: Москва
Может, дело в классе (методах класса) ResultSet?
Alt 28.01.2004, 17:06   #7  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Вообще-то, как я уже писал, я делал то же самое через QueryRun, т.е. цикл имел вид:

while (qr.next())
{
inventTable = qr.get(tablenum(InventTable));
fileOut.write(inventTable.ItemGroupID,inventTable.ItemID,...);
}

Скорость осталась примерно такая же как и при ResulSet. Т.е. явно медленнее, чем прямое сканирование табличной переменной. Конечно R.getString() влияет, только какое-то непонятное влияние.
Alt 28.01.2004, 17:36   #8  
mazzy ist offline
mazzy
Участник
Benutzerbild von mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29.472 / 4494 (208) ++++++++++
Registriert seit: 29.11.2001
Ort: Москва
Blog-Einträge: 10
Владимир Максимов, я совсем запутался.

Так кто на ком стоял? Какой метод быстрее, а какой медленнее?
Вы можете привести время для способа 1 и способа 2?
Alt 28.01.2004, 17:45   #9  
EVGL ist offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4.445 / 3001 (0) ++++++++++
Registriert seit: 09.07.2002
Ort: Parndorf, AT
ResultSet у него работает медленнее. С самого начала он так написал.
Я другого не понимаю: чего автор тут добивается? От гневных реплик кэширование, выполняемое ядром Аксапта в 2-уровневом ли, в 3-уровневом режимах для таблиц, явно описанных в AOT, в ResultSet не появится. И исходных кодов у нас нет, чтобы посмотреть, через сколько COM-компонентов и промежуточных интерфейсов работает ResultSet.
Alt 28.01.2004, 17:48   #10  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Самый быстрый способ - это сканирование таблицы, т.е.

while select inventTable ...

ну или как я написал в примере

select * from inventTable;
while (i<=1000) ...

Выбрасывает около 5тыс строк из 40 полей разного типа примерно за 5 секунд

Использование ResultSet или QueryRun на той же выборке дает время на порядок медленнее (примерно 50 секунд). Есть некоторое расхождение между использованием ResultSet и QueryRun, но в пределах погрешности (несколько секунд).

Вот я и пытаюсь понять: почему собственно? Подчеркну - кроме собственно commaIo.write() внутри цикла while ничего нет (ну, кроме QueryRun.get())
Alt 28.01.2004, 17:49   #11  
andreynikolai ist offline
andreynikolai
Участник
 
133 / 10 (1) +
Registriert seit: 11.04.2002
Скорее всего чтение из табличной переменной действительно быстрее потому что
resultSet табличной переменной кэширован.
А ResultSet полученный путем класса userConnection не кэшируется. Не
предусмотрено наверное.
Alt 28.01.2004, 18:04   #12  
Wamr ist offline
Wamr
----------------
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
1.737 / 868 (32) +++++++
Registriert seit: 15.01.2002
Ort: Москва
Blog-Einträge: 7
Посмотрите в Profiler как обрабатываются ваши запросы SQL-сервером
Alt 28.01.2004, 18:09   #13  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Wamr
Может быть я чего-то не понимаю, но Вы хотите сказать, что на каждом шаге цикла, по команде next запрос SQL выполняется заново?
Время выполнения собственно запросов (на 5 тыс строк) на самом MS SQL 2000 составляет менее секунды
Alt 28.01.2004, 18:14   #14  
mazzy ist offline
mazzy
Участник
Benutzerbild von mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29.472 / 4494 (208) ++++++++++
Registriert seit: 29.11.2001
Ort: Москва
Blog-Einträge: 10
Zitat:
Изначально опубликовано andreynikolai
Скорее всего чтение из табличной переменной действительно быстрее потому что
resultSet табличной переменной кэширован.
Согласен. Если посмотреть на свойства таблицы inventTable, то увидим, что у нее установлено свойство CachLookup = Found.

select ... where этим свойством пользуется.
ResultSet вроде не пользуется.
Всегда считал, что query тоже этим свойством пользуется...

Владимир Максимов, скорость выполнения сравнивалась при первом после входа запуске или при повторных запусках? Что будет, если отключить кэширование, выйти, зайти и протестировать еще раз?
Alt 28.01.2004, 18:25   #15  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Видимо, я ненамеренно ввел в заблуждение тем, что использовал в примере таблицу InventTable. На самом деле, при проверке использовалась собственная таблица (в том смысле, что не основная) и у этой таблицы CachLookup = None (данные по времени приведены именно для такой настройки). Хотя использование InventTable не противоречит полученным результатам.

Результаты проверок от повторных запусков зависят слабо. Разница в пределах погрешности (несколько секунд). Сейчас убегаю, завтра продолжим
Alt 28.01.2004, 19:12   #16  
Wamr ist offline
Wamr
----------------
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
1.737 / 868 (32) +++++++
Registriert seit: 15.01.2002
Ort: Москва
Blog-Einträge: 7
Я знаю, что while select работает через курсоры и вытягивает записи с сервера (fetch) кусками по несколько записей. Как отрабатывает ResultSet я не знаю. Но раз уж вы заинтересовались этой темой, то было бы логично посмотреть именно работу SQL-сервера.
Так же было замечено, что ResultSet тормозит при определении конца цикла . Можно попробовать сделать top 110 а по счетчику оборвать цикл на 100 записях.
Alt 28.01.2004, 19:56   #17  
Vadik ist offline
Vadik
Модератор
Benutzerbild von Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3.631 / 1853 (69) ++++++++
Registriert seit: 18.11.2002
Ort: гражданин Москвы
слушайте Wamr'a, Wamr плохого не посоветует

достаточно посмотреть на то, что попадает в профайлер в каждом проходе в первом цикле и что во втором

а) Connection, Statement
аксапта "честно" отправляет запрос "select top 1000 from myTable"
-exec sp_cursoropen ...
открывает курсор и фетчит записи ПО ОДНОЙ
-exec sp_cursorfetch 180150058, 2, 1, 1 - по одному вызову на запись
обратите внимание на последний параметр (1) и вот это

б) WHILE SELECT и табличная переменная
-exec sp_cursorexecute - у нас есть уже есть "откомпилированный" MSSQL запрос, так что мы его используем повторно. MSSQL не парсит его повторно, не строит план исполнения (он уже есть), это хорошо, что-то мы на этом сэкономили.
но все это фигня
-exec sp_cursorfetch 180150050, 2, 1, 16 - по одному вызову на несколько записей
обратите внимание на последний параметр, он равен 16 (у меня так с последней версией MDAC, сколько будет у вас - не знаю)
т.е. мы получаем recordset кусками по 16 записей
в конечном счете мы немного выиграли на суммарном траффике
но и это тоже фигня

мы сделали В РАЗЫ меньше fetch() по сравнению с первым вариантом

ну а раз время выполнение SELECT * FROM MYTABLE у нас мало по сравнению со временем на то, чтобы отослать результаты клиенту (запрос тривиальный), выигрыш у нас идет в разы, если не на порядок

а кэширование тут не при чем, SELECT * FROM MYTABLE, даже с условием WHERE, но не по уникальному ключу у нас не кэшируются, разве что с CacheLookup=EntireTable, но этот случай мы рассматривать не будем..

З.Ы. вот уж дорвался до форума так дорвался
З.З.Ы. до QueryRun не добрался, как-нибудь потом

подумалось.. насчет зависимости числа fetch-ащихся записей от версии MDAC я похоже того.. немного погорячился для одинаковых версий аксапты оно скорее всего будет одинаковым
Alt 28.01.2004, 20:00   #18  
mazzy ist offline
mazzy
Участник
Benutzerbild von mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29.472 / 4494 (208) ++++++++++
Registriert seit: 29.11.2001
Ort: Москва
Blog-Einträge: 10
Zitat:
Изначально опубликовано Vadik
а кэширование тут не при чем, SELECT * FROM MYTABLE, даже с условием WHERE, но не по уникальному ключу у нас не кэшируются
ок. спасибо.
Alt 29.01.2004, 10:38   #19  
Владимир Максимов ist offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1.726 / 1208 (44) ++++++++
Registriert seit: 13.01.2004
Blog-Einträge: 3
Vadik
Как Вы получили эти числа в профайлере? У меня как я ни кручу профайлер ничего подобного не наблюдается (Axapta 2.5). В профайлере я вижу только дерево вызовов. Т.е. сколько времени на какую строку ушло.

Если судить по времени обработке строк, получается, что Statment фетчит по одной записи, а While Select по 24 за раз.

НО!

Если просуммировать время фетча для 24 строк Statmenta и сравнить с временем фетча для одной строки While Select, то я получаю примерно одинаковое значение.

Принципиальное расхождение по времени наблюдается именно на команде записи в текстовый файл! В моем случае на 2 порядка.

Опять же, судя по плану выполнения запроса в профайлере индексы используются в обеих случаях. Точнее используется кластерный индекс. Собственно, этого и следовало ожидать. Здесь же идет голое сканирование строк в соответствии именно с кластерным индексом.

И еще, опять же судя по результатам профайлера, почему-то при выполнении Statment наблюдается повышенный обмен данными с сервером. У меня получились такие данные (только собственно цикл While):

Satment
Вызовов от клиента к серверу 0
Байт, от клиента к серверу 571969
Вызовов от сервера к клиенту 21001
Байт, от сервера к клиенту 1040040

While Select
Вызовов от клиента к серверу 0
Байт, от клиента к серверу 425451
Вызовов от сервера к клиенту 41
Байт, от сервера к клиенту 1435

Т.е. каким-то образом оптимизируется объем передаваемой информации. Единственная причина, которая приходит в голову - это информация о типах данных. О типах данных "родной" таблицы и так все известно, а вот о типах Satament - ничего не ясно. Хотя тут я не уверен.
Alt 29.01.2004, 18:57   #20  
Vadik ist offline
Vadik
Модератор
Benutzerbild von Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3.631 / 1853 (69) ++++++++
Registriert seit: 18.11.2002
Ort: гражданин Москвы
Вообще-то я имел в виду профайлер от MSSQL, события
RPC:Completed
SQL:BatchCompleted
в нем все чудесно видно

по поводу использования индексов: речь вроде шла о кэшировании, при чем тут индексы?

По поводу траффика - ну да, по объему выигрыш около 25 процентов. Зато какая разница в количестве вызовов! Похоже, AOS и клиент тоже обмениваются пачками записей, а каждое обращение к Resultset, который живет на сервере - это лишний вызов, а на него тоже время требуется (и траффик). За счет этого и получается такой проигрыш

По мне, так Connection если и нужен, то для того, чтобы выполнить в нем что-то короткое типа exec myproc, truncate mytable. Работать с ним как-то по-другому - только лишний головняк
This post has been rated by: Logger (3).
Stichworte
connection, profiler, sql, statement, полезное, производительность, профайлер

 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Расхождение суммы проводки по поставщику и сопоставленной суммы petr DAX: Функционал 2 15.10.2008 23:31
Почему loka DAX: Программирование 2 01.12.2005 17:36
Ускорение выполнения запроса Oracle + MS Axapta Горбунов Дмитрий DAX: Программирование 17 15.11.2005 18:13
Профили выполнения проводки George V. Tavrizoff DAX: Функционал 8 07.09.2004 16:56
Можно ли проследить историю выполнения заказа? Hard DAX: Функционал 3 14.08.2003 10:06

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Gehe zu

Рейтинг@Mail.ru
Alle Zeitangaben in WEZ +3. Es ist jetzt 05:14 Uhr.
Powered by vBulletin® Version 3.8.5 (Deutsch)
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.