Поправки к статье «Сравнение скорости доступа к данным (ADO.NET, ADO, ascDB)»

Автор: Станислав Михайлов
optim.su

Источник: RSDN Magazine #1-2003
Опубликовано: 11.05.2003
Версия текста: 1.0
Предисловие
Описание изменений, произошедших в коде теста ChangeData
Описание изменений, произошедших в коде теста Forward
Новые результаты теста ChangeData
Коррекция выводов, сделанных в предыдущей статье
Заключение

Предисловие

К сожалению, при тестировании средств доступа к базам данных (ADO.Net, ADO, ascDB) в одном из тестов были допущены несколько ошибок. После исправления ошибок оказалось необходимым внести некоторые корректировки в результаты тестирования, приведенные в предыдущей статье. Я приношу читателям свои извинения, каюсь и надеюсь, что подобного более не повторится.

Кроме упомянутых выше, есть и ещё одна причина, из-за которой я возвращаюсь к старой теме. Дело в том, что разработчикам удалось существенно ускорить ascDB в самом узком месте, а именно снизить время сохранения данных после их изменения примерно в полтора раза.

К сожалению, повторить старые условия тестирования не представилось возможным, поскольку изменились конфигурации машин, участвующих в тесте (в том числе изменились операционные системы, установленные на них).

Естественно, что, учитывая ошибки и изменение конфигурации, бессмысленно сравнивать новые данные со старыми. Однако, все описания тестов и выводы, сделанные в предыдущей статье, остаются в силе, за исключением изменений, описанных ниже. Так уж получилось, что результаты неверных тестов оказались недалеки от истины. :)

Описание изменений, произошедших в коде теста ChangeData

Где же были допущены ошибки и как они сказались на результатах тестирования? Все ошибки, коварно маскируясь во мраке кода, закрались в тест ChangeData.

Первая, самая непростительная и существенная из ошибок, "поразила" область выполнения операции Update, бесчестно сведя к минимуму количество реально выполняемых изменений данных в строках курсора. В коде теста после каждого вызова метода CursorUpdate находился лишний, вероятно, забытый в результате многочисленных правок, вызов метода CursorFetchRandom. Ниже приведен фрагмент кода с ошибкой (переменная curs представляет собой ascVisualCursor (ascDB), Recordset (ADO) или DataSet (ADO.Net)):

For j = 1 To 10
    CursorUpdate curs
    CursorFetchRandom curs, iPosition30
Next

Понятно, что в этом случае на клиенте выполнялось 10 модификаций одной и той же строки, но на сервере операция Update выполнялась только один раз для одной строки вместо изменения значений в десяти строках. Правильный код выглядит так:

For j = 1 To 10
     CursorUpdate curs
     CursorFetchNext curs
Next

Исправление этой ошибки привело к изменению результатов теста ChangeData. Это произошло за счёт увеличения времени записи изменений для всех тестируемых средств доступа к базам данных.

Вторая ошибка заключалась в том, что в тесте ChangeData для ADO в методах CursorInsert, CursorDelete и CursorUpdate при нахождении курсора в состоянии EOF вызывался метод MovePrevious объекта Recordset. Это могло привести к значительным потерям времени в случае, когда курсор не был отключен от базы данных (из-за крайне медленной работы навигации по курсору ADO в connected-режиме).

Реорганизация теста позволила избежать ситуации EOF, в результате чего время выполнения операций Update и Delete в тесте ADO (connected-режим) очень сильно сократилось. Про операцию Insert сказано ниже (в описании третьей ошибки).

Третья и, надеюсь, последняя ошибка относилась только к методу CursorInsert теста ChangeData для ADO. Случайным и невероятным образом из кода этого метода исчезла крайне необходимая строка «ars.AddNew» (в которой ars является объектом Recordset), что неизбежно привело в полному отсутствию реальных вставок строк в тесте.

После добавления исчезнувшей строки время выполнения операции Insert (в тесте ChangeData для ADO), разумеется, возросло.

Описание изменений, произошедших в коде теста Forward

Изменения в тесте Forward коснулись только ADO.NET.

В результате внимательного рассмотрения проблемы больших затрат времени на выполнение метода Close объектов SqlDataReader и OleDbDataReader оказалось, что при попытке закрыть Reader выполняется докачка всех еще не считанных записей. Чтобы избежать этой неприятности при переоткрытии объекта в случае циклического повторения теста, были внесены изменения в код метода CloseReader тестового приложения. В старом коде выполнялось простое закрытие объекта SqlDataReader:

m_sdrReader.Close();

В новом коде дополнительно вызывается метод Cancel команды (объекта SqlCommand или OleDbCommand, в зависимости от определения #define CompileWithSqlClient или CompileWithOleDb):

m_cmd.Cancel();
m_sdrReader.Close();

После вызова метода Cancel команды, Reader закрывается намного быстрее. Однако появились проблемы. Иногда после этой операции в SQL-сервере появлялись блокировки, которые приводили к зависанию теста (с выдачей таймаута).

Новые результаты теста ChangeData

Анализируя новые результаты тестов, необходимо учитывать, что, помимо исправления ошибок, произошли следующие изменения.

В качестве клиентской машины во всех случаях использовался компьютер со следующими параметрами:

  1. ОС: Microsoft Windows XP Professional (Version 5.1.2600)

В качестве серверной машины в случае удаленных тестов использовался компьютер со следующими параметрами:

Тестовые приложения и библиотеки ADO.NET скомпилированы на C# из поставки Microsoft Development Environment 2003 Beta (Version 7.1.2292), Microsoft .Net Framework 1.1 (Version 1.1.4322).

Сам тест ChangeData был несколько реорганизован (увеличилось количество вызовов метода CursorFetch), увеличилось и количество вызовов методов CursorInsert и CursorUpdate.

Также нельзя забывать, что скорость записи изменений в курсоре ascDB была существенно увеличена разработчиками. Поэтому, несмотря на увеличение количества измененных строк, произошедшее в результате исправления ошибок, время записи изменений в ascDB сократилось почти вдвое. Дальнейшее ускорение работы ascDB представляется маловероятным по той причине, что ascDB поддерживает механизм триггеров, который в текущей версии невозможно отключить. Данные перед любой модификацией извлекаются из БД и передаются в триггерные события. К тому же модификация данных производится с помощью курсоров, что на некоторых СУБД дает дополнительные задержки.

Ниже приведены новые результаты тестов.

ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopen
Количество повторов операции11501100115039301010
Таблица 1. Общее количество операций по 10 итерациям теста ChangeData (одинаково для всех тестов)

ChangeData (10 итераций)InProcess ClientCOM+ ClientNet RemotingClientCOM+ ServerNet Remoting Server
ADO.NET21.17250.24267.775205.957194.74
ADO (в скобках – disconnected)39.156 (13.539)17.715нет33.808нет
AscDB17.05518.177нет32.046нет
Таблица 2. Результаты теста ChangeData

Как видно по таблице, общее время выполнения теста ADO.NET в удаленном режиме значительно меньше, чем время выполнения того же теста в соответствующих локальных режимах. Вероятнее всего, это связано с использованием в качестве клиента более быстрой машины с большим объемом оперативной памяти. В результате разница в скорости копирования данных при их десериализации на клиенте оказалась существенной, и даже передача данных по сети не смогла сгладить разницу. Подробнее о причинах медленной сериализации объекта DataSet было сказано в предыдущей статье. Единственное, что можно добавить – похоже, DataSet всегда сериализуется в XML. Однако вряд ли этим фактом можно объяснить столь медленную сериализацию.

ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего
ADO.NET0.0200.0700.000.03014.1296.92121.170
ADO (connected)0.3100.1700.0229.9427.0301.67439.156
ADO (disconnected)0.3610.4810.070.6017.2094.81713.539
ascDB0.4610.6010.012.05310.6853.24517.055
Таблица 3. Результаты теста ChangeData по операциям. Режим in-process.

ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего
ADO.NET0.080.1520.020.02021.682228.286250.240
ADO0.360.4510.080.6415.45810.72517.715
ascDB0.480.4710.022.84510.9653.39618.177
Таблица 4. Результаты теста ChangeData по операциям. Локальный режим через COM+

ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего
ADO.NET0.040.040.010.00026.11179.757205.957
ADO0.110.170.000.2706.51026.74833.808
ascDB0.6530.170.0115.47911.7084.02632.046
Таблица 5. Результаты теста ChangeData по операциям. Удаленный режим через COM+

Коррекция выводов, сделанных в предыдущей статье

Преимущество ADO (disconnected-режим) над ascDB теперь представляется незначительным. Хотя нельзя забывать о том, что в disconnected-режиме ADO вынуждено передавать весь курсор на клиента, а ascDB – нет. Дело в том, что ascDB реализует полноценную докачку (поблочную) данных, что можно сравнить с обычным connected-режимом ADO. Однако, во-первых, в обычном режиме ADO показало намного худшие результаты, а во-вторых, disconnected-режим – единственный разумный режим для ADO, так как подключенный курсор в ADO передается по ссылке, и любой вызов метода будет осуществляться по сети.

Неверным оказался вывод о низкой скорости выполнения операции Delete в ADO (connected-режим): в этом режиме тормозит только операция Fetch (т.е. Move метода Recordset).

Подтвердилось, что увеличение объема оперативной памяти сверх 256 Мб существенно ускоряет работу ADO.NET, тогда как для ADO и ascDB вполне достаточно 256 Мб (разумеется, речь идет о тесте ChangeData, так как остальные тесты не изменялись).

Прочие выводы остались без изменений.

Заключение

Я ещё раз приношу читателям искренние извинения за допущенные ошибки.

Возможно, памятуя о непростительности ошибок в подобных тестах, автору следовало бы совершить ритуальное самоубийство, но надеюсь, что отсутствие среди предков автора самураев позволяет мне сохранить себе жизнь и рассчитывать в дальнейшем на прощение читательской аудиторией :-).


Эта статья опубликована в журнале RSDN Magazine #1-2003. Информацию о журнале можно найти здесь