Прочитав следующую статью, я обнаружил, что авторский тест действительно полезен друзьям, использующим ASP. Он должен быть одинаковым не только для ASP, но и для других языков. Генерация динамического контента на сервере — одна из основных причин использования ASP, поэтому первый тестовый проект, который мы выбрали, заключался в определении наилучшего метода отправки динамического контента в поток ответов. Существует два основных варианта (и некоторые их варианты): использование встроенных тегов ASP и использование оператора Response.Write.
Чтобы протестировать эти различные подходы, мы создали простую страницу ASP, на которой были определены некоторые переменные, а затем вставлены их в таблицу. Хотя эта страница проста и бесполезна, ее достаточно, чтобы мы могли изолировать и протестировать отдельные проблемы.
2.1 Использование встроенных тегов ASP
Первый тест — использовать встроенный тег ASP <%= x %>, где x — переменная. Это наиболее удобный метод, который упрощает чтение и обслуживание HTML-части страницы.
Скопируйте код кода следующим образом:
<% ОПЦИЯ ЯВНЫЙ
Дим Имя
Димфамилия
Тусклый средний начальный
Тусклый адрес
Дим Сити
Тусклый штат
ДимТелефонНомер
Тусклый номер факса
Тусклый адрес электронной почты
ДимДатаРождения
Имя = Джон
СреднийНачало = Q
Фамилия = Публичный
Адрес = Мейн-стрит, 100.
Город=Нью-Йорк
Штат = Нью-Йорк
Номер телефона = 1-212-555-1234
Номер факса = 1-212-555-1234
Электронная почта = [email protected]
Дата рождения = 01.01.1950
%>
<HTML>
<ГОЛОВКА>
<TITLE>Тест ответа</TITLE>
</HEAD>
<ТЕЛО>
<H1>Тест ответа</H1>
<ТАБЛИЦА>
<tr><td><b>Имя:</b></td><td><%= Имя %></td></tr>
<tr><td><b>Средний инициал:</b></td><td><%= MiddleInitial %></td></tr>
<tr><td><b>Фамилия:</b></td><td><%= Фамилия %></td></tr>
<tr><td><b>Адрес:</b></td><td><%= Адрес %></td></tr>
<tr><td><b>Город:</b></td><td><%= Город %></td></tr>
<tr><td><b>Состояние:</b></td><td><%= Состояние %></td></tr>
<tr><td><b>Номер телефона:</b></td><td><%= PhoneNumber %></td></tr>
<tr><td><b>Номер факса:</b></td><td><%= FaxNumber %></td></tr>
<tr><td><b>Электронная почта:</b></td><td><%= Электронная почта %></td></tr>
<tr><td><b>Дата рождения:</b></td><td><%= Дата рождения %></td></tr>
</ТАБЛИЦА>
</ТЕЛО>
</HTML>
Полный код /app1/response1.asp
Лучшая запись = 8,28 мс/стр.
2.2. Используйте Response.Write для вывода каждой строки HTML-кода.
Существует много хорошей литературы, в которой говорится, что следует избегать предыдущего подхода к встроенной разметке, поскольку он приводит к операции, называемой переключением контекста. Эта операция происходит при изменении типа кода, обрабатываемого веб-сервером (с отправки чистого HTML на обработку скрипта или наоборот), и это переключение занимает определенное количество времени. После того, как многие программисты это усвоят, их первой реакцией будет использование функции Response.Write для вывода каждой строки HTML-кода:
Скопируйте код кода следующим образом:
...
Response.Write(<html>)
Response.Write(<голова>)
Response.Write( <title>Тест ответа</title>)
Ответ.Запись(</head>)
Response.Write(<тело>)
Response.Write(<h1>Тест ответа</h1>)
Response.Write(<таблица>)
Response.Write(<tr><td><b>Имя:</b></td><td> & Имя & </td></tr>)
Response.Write(<tr><td><b>Средний инициал:</b></td><td> & MiddleInitial & </td></tr>)
...
Фрагмент /app1/response2.asp
Лучшая запись = 8,28 мс/стр.
Время отклика = 8,08 мс/стр.
Разница = -0,20 мс (снижение на 2,4%)
Улучшение производительности, которое мы увидели по сравнению с версией со встроенной разметкой, было настолько небольшим, что это было просто удивительно. Это может быть связано с тем, что на странице гораздо больше вызовов функций. Однако у этого метода есть больший недостаток. Поскольку HTML-код встроен в функцию, код сценария становится очень длинным и неудобным для чтения и обслуживания.
2.3 Использование функций-оболочек
Response.Write не добавляет CRLF (возврат каретки — перевод строки, возврат каретки — перевод строки) в конец текстовой строки, что является самым разочаровывающим аспектом использования вышеуказанного метода. Хотя HTML-код хорошо отформатирован на стороне сервера, в браузере вы видите всего лишь одну длинную строку кода. Но эта проблема была не единственным разочарованием. Вскоре люди обнаружили, что не существует функции Response.WriteLn, которая могла бы автоматически добавлять CRLF. Естественная реакция — создать функцию-обертку для Response.Write и добавлять CRLF после каждой строки:
...
writeCR(<tr><td><b>Имя:</b></td><td> & Имя & </td></tr>)
...
ПОДПИСАНИЕCR(str)
Response.Write(str & vbCRLF)
КОНЕЦ ПОДПИСКИ
Фрагмент /app1/response4.asp
Лучшая запись = 8,08 мс/стр.
Время отклика = 10,11 мс/стр.
Разница = +2,03 мс (увеличение на 25,1%)
Результатом является значительное снижение производительности. Конечно, главным образом потому, что этот метод удваивает количество вызовов функций, и его влияние на производительность весьма очевидно. Этого использования следует избегать любой ценой, CRLF приводит к появлению двух дополнительных байтов в конце каждой строки, и эти два байта бесполезны для браузера при отображении страницы. В большинстве случаев красивый формат HTML-кода на стороне браузера просто облегчает вашим конкурентам чтение и понимание дизайна страницы.
2.4 Объединение нескольких ответов Response.Write
Если игнорировать последний тест по инкапсуляции функций, следующим логическим шагом будет объединение всех строк из отдельных операторов Response.Write в один оператор, тем самым уменьшая количество вызовов функций и повышая эффективность кода.
Скопируйте код кода следующим образом:
Response.Write(<html> & _
<голова> & _
<title>Тест ответа</title> & _
</head> & _
<тело> & _
<h1>Тест ответа</h1> & _
<таблица> & _
<tr><td><b>Имя:</b></td><td> & Имя & </td></tr> & _
...
<tr><td><b>Дата рождения:</b></td><td> & Дата рождения & </td></tr> & _
</таблица> & _
</body> & _
</html>)
Фрагмент /app1/response3.asp
Лучшая запись = 8,08 мс/стр.
Время отклика = 7,05 мс/стр.
Разница = -1,03 мс (снижение на 12,7%)
Это, безусловно, лучший метод.
2.5 Объедините несколько ответов. Напишите и добавьте CRLF в конце каждой строки.
Некоторые люди также очень обеспокоены тем, красиво ли их HTML-код выглядит на стороне браузера, поэтому мы добавляем возврат каретки в конце каждой строки HTML-кода, используя константу vbCRLF. Остальные тестовые коды такие же, как в приведенном выше примере. .
...
Response.Write(<html> & vbCRLF & _
<head> & vbCRLF & _
<title>Тест ответа</title> & vbCRLF & _
</head> & vbCRLF & _
...
Фрагмент /app1/response5.asp
Лучшая запись = 7,05 мс/стр.
Время отклика = 7,63 мс/стр.
Разница = +0,58 мс (увеличение на 8,5%)
В результате происходит небольшое снижение производительности, вероятно, из-за добавления операций конкатенации строк и увеличения выходного текста.
2.6 Комментарии
По результатам приведенного выше теста вывода ASP мы приходим к следующим правилам кодирования:
Избегайте слишком частого использования встроенного ASP.
Объедините как можно больше операторов Response.Write в один оператор.
Никогда не инкапсулируйте Response.Write только для добавления CRLF.
Если вы хотите отформатировать вывод HTML, добавьте CRLF непосредственно после оператора Response.Write.
Краткое описание: Каков наиболее эффективный способ вывода контента, динамически создаваемого ASP? Как лучше всего извлечь набор записей базы данных? В этой статье тестируется около 20 распространенных проблем при такой ASP-разработке. Время, отображаемое инструментом тестирования, говорит нам: эти проблемы, которые обычно считаются само собой разумеющимися, не только достойны внимания, но и таят в себе неожиданные секреты.
1. Цель испытания
В первой части этой статьи рассматриваются некоторые основные вопросы разработки ASP и приводятся некоторые результаты тестов производительности, которые помогут читателям понять, какое влияние код, размещенный на странице, оказывает на производительность. ADO — универсальный, простой в использовании интерфейс базы данных, разработанный Microsoft. Оказывается, взаимодействие с базой данных посредством ADO — одно из важнейших приложений ASP. Во второй части мы изучим этот вопрос.
Функционал, предоставляемый ADO, довольно обширен, поэтому самая большая трудность при подготовке этой статьи состоит в том, как определить масштаб проблемы. Учитывая, что извлечение больших объемов данных может существенно увеличить нагрузку на веб-сервер, мы решили, что основная цель этого раздела — выяснить, какова оптимальная конфигурация для работы наборов записей ADO. Однако даже после сужения масштаба проблемы мы по-прежнему сталкиваемся с большими трудностями, поскольку у ADO может быть много разных способов выполнить одну и ту же задачу. Например, наборы записей можно извлекать не только через класс Recordset, но и через классы Connection и Command, даже после получения объекта набора записей существует множество методов работы, которые могут существенно повлиять на производительность; Однако, как и в первой части, мы постараемся охватить максимально широкий круг вопросов.
В частности, цель этого раздела — собрать достаточно информации для ответа на следующие вопросы:
Следует ли ссылаться на ADOVBS.inc через include?
lСледует ли мне создавать отдельный объект подключения при использовании наборов записей?
lКак лучше всего извлечь набор записей?
lКакой тип курсора и метод блокировки записи являются наиболее эффективными?
lСледует ли мне использовать локальный набор записей?
lКак лучше всего настроить свойства набора записей?
lКакой метод наиболее эффективен для ссылки на значения полей в наборе записей?
lЭто хороший способ собрать выходные данные с помощью временной строки?
2. Тестовая среда
Всего в этом тесте использовался 21 файл ASP, который можно скачать в конце этой статьи. Каждая страница настроена на выполнение трех разных запросов, возвращающих 0, 25 и 250 записей соответственно. Это поможет нам изолировать накладные расходы на инициализацию и работу самой страницы от накладных расходов, связанных с циклическим перебором набора записей.
Для облегчения тестирования строка подключения к базе данных и строка команды SQL сохраняются как переменные приложения в Global.asa. Поскольку нашей тестовой базой данных является SQL Server 7.0, в строке подключения в качестве поставщика подключения указывается OLEDB, а тестовые данные поступают из базы данных SQL Server Northwind. Команда SQL SELECT извлекает 7 указанных полей из таблицы заказов NorthWind.
Скопируйте код кода следующим образом:
<SCRIPT LANGUAGE=VBScript RUNAT=Сервер>
Подприложение_OnStart
Приложение (Conn) = Поставщик = SQLOLEDB; & _
Сервер=МойСервер; & _
uid = са; & _
пвд=; & _
БАЗА ДАННЫХ = северный ветер
Приложение (SQL) = SELECTTOP 0OrderID и _
идентификатор клиента и _
Идентификатор сотрудника и _
Дата заказа и _
Требуемая дата и _
Дата отгрузки и _
Груз & _
ОТ[Заказы]
Конец субтитра
</СКРИПТ>
'альтернативный sql - 25 записей
Приложение (SQL) = SELECTTOP 25OrderID и _
идентификатор клиента и _
Идентификатор сотрудника и _
Дата заказа и _
Требуемая дата и _
Дата отгрузки и _
Груз & _
ОТ[Заказы]
'альтернативные записи sql-250
Приложение (SQL) = SELECTTOP 250 OrderID и _
идентификатор клиента и _
Идентификатор сотрудника и _
Дата заказа и _
Требуемая дата и _
Дата отгрузки и _
Груз & _
ОТ[Заказы]
Конфигурация тестового сервера была следующей: 450 МГц Pentium, 512 МБ ОЗУ, NT Server 4.0 SP5, MDAC 2.1 (компонент доступа к данным) и Microsoft Scripting Engine версии 5.0. SQL Server работает на другом компьютере с аналогичной конфигурацией. Как и в первой части, мы по-прежнему используем Microsoft Web Application Stress Tool для записи времени от запроса первой страницы до последнего байта, полученного от сервера (TTLB, Time To Last Byte), время указывается в миллисекундах. Тестовый сценарий вызывал каждую страницу более 1300 раз, и его выполнение заняло около 20 часов. Время, указанное ниже, представляет собой среднее значение TTLB для сеанса. Помните, что, как и в первой части, нас интересует только эффективность кода, а не его масштабируемость или производительность сервера.
Также обратите внимание, что мы включили буферизацию сервера. Кроме того, чтобы сделать все имена файлов одинаковой длины, в имена некоторых файлов встроено одно или несколько подчеркиваний.
3. Первый тест
В первом тесте мы извлекли набор записей, имитирующий типичный сценарий, найденный в примерах Microsoft ASP ADO. В этом примере (ADO__01.asp) мы сначала открываем соединение, а затем создаем объект набора записей. Конечно, скрипт здесь оптимизирован в соответствии с правилами кодирования, изложенными в первой части этой статьи.
Скопируйте код кода следующим образом:
<% Опция явная %>
<!-- #Include file=ADOVBS.INC -->
<%
Тусклый объект objConn
Тусклый объект
Ответ.Запись(_
<HTML><HEAD> и _
<TITLE>Тест ADO</TITLE> & _
</HEAD><BODY> _
)
Установите objConn = Server.CreateObject(ADODB.Connection)
objConn.Открыть приложение (Conn)
Установите objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.Открыть приложение (SQL)
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'написать заголовки
Ответ.Запись(_
<ГРАНИЦА ТАБЛИЦЫ=1> & _
<ТР> & _
<TH>Идентификатор заказа</TH> и _
<TH>Идентификатор клиента</TH> и _
<TH>ID сотрудника</TH> и _
<TH>Дата заказа</TH> и _
<TH>Требуемая дата</TH> & _
<TH>Дата отправки</TH> и _
<TH>Грузовые перевозки</TH> и _
</TR> _
)
'записать данные
Делайте, пока не objRS.EOF
Ответ.Запись(_
<ТР> & _
<TD> & objRS(OrderID) & </TD> & _
<TD> & objRS(CustomerID) & </TD> & _
<TD> & objRS(EmployeeID) & </TD> & _
<TD> & objRS(OrderDate) & </TD> & _
<TD> & objRS(RequiredDate) & </TD> & _
<TD> & objRS(ShippedDate) & </TD> & _
<TD> & objRS(Грузовые перевозки) & </TD> & _
</TR> _
)
objRS.MoveNext
Петля
Ответ.Запись(</TABLE>)
Конец, если
objRS.Close
objConn.Close
Установить objRS = Ничего
Установить objConn = Ничего
Ответ.Запись(</BODY></HTML>)
%>
Вот результаты испытаний:
Давайте посмотрим, что означают цифры в каждом столбце:
0 возвращает TTLB (в миллисекундах), необходимый для страницы с 0 записями. Во всех тестах это значение считается затратами времени на генерацию самой страницы (включая создание объектов), исключая время перебора данных набора записей.
25 TTLB в миллисекундах для выборки и отображения 25 записей
TTLB в столбце «Общее время/2525» делится на 25, что соответствует общей средней стоимости времени на запись.
время отображения/2525 TTLB столбца минус 0 TTLB столбца, затем разделите на 25. Это значение отражает время, необходимое для отображения одной записи при циклическом просмотре набора записей.
250 Извлекает и отображает TTLB из 250 записей.
TTLB в столбце общее время/250250 делится на 25. Это значение представляет собой общую среднюю стоимость времени одной записи.
disp time/250 Значение TTLB в столбце 250 вычитается из значения TTLB в столбце 0, а затем делится на 250. Это значение отражает время, необходимое для отображения одной записи при циклическом просмотре набора записей.
Приведенные выше результаты испытаний будут использоваться для сравнения с результатами следующих испытаний.
4. Следует ли ссылаться на ADOVBS.inc посредством включения?
ADOVBS.inc, предоставленный Microsoft, содержит 270 строк кода, определяющих большинство констант свойств ADO. Наш пример ссылается только на две константы из ADOVBS.inc. Поэтому в этом тесте (ADO__02.asp) мы удалили ссылку на включенный файл и напрямую использовали соответствующее значение при настройке свойств.
objRS.CursorType = 0?'
objRS.LockType = 1' adLockReadOnly
Вы можете видеть, что накладные расходы страницы снизились на 23%. Это значение не влияет на время выборки и отображения отдельных записей, поскольку изменения здесь не влияют на операции набора записей внутри цикла. Существует несколько способов решения проблем со ссылками на ADOVBS.inc. Мы рекомендуем использовать файл ADOVBS.inc в качестве справочного материала и объяснять настройки в комментариях. Помните, как отмечалось в части 1, умеренное использование комментариев минимально влияет на эффективность вашего кода. Другой способ — скопировать на страницу нужные вам константы из файла ADOVBS.inc.
Существует также хороший способ решить эту проблему: сделать все константы ADO напрямую доступными, подключив их к библиотеке типов ADO. Добавьте следующий код в файл Global.asa для прямого доступа ко всем константам ADO:
<!--ТИП МЕТАДАННЫХ=typelib
ФАЙЛ=C:Program FilesОбщие файлыSYSTEMADOmsado15.dll
NAME=Библиотека типов ADODB -->
или:
<!--ТИП МЕТАДАННЫХ=typelib
UUID=00000205-0000-0010-8000-00AA006D2EA4
NAME=Библиотека типов ADODB -->
Поэтому наше первое правило:
lИзбегайте включения файла ADOVBS.inc, а также получайте доступ и используйте константы ADO другими методами.
5. Должен ли я создавать отдельный объект подключения при использовании набора записей?
Чтобы правильно ответить на этот вопрос, мы должны проанализировать тест при двух разных условиях: во-первых, на странице есть только одна транзакция базы данных, во-вторых, на странице есть несколько транзакций базы данных;
В предыдущем примере мы создали отдельный объект Connection и присвоили его свойству ActiveConnection набора записей. Однако, как показано в ADO__03.asp, мы также можем назначить строку подключения непосредственно свойству ActiveConnection, исключив дополнительный этап инициализации и настройки объекта Connection в сценарии.
objRS.ActiveConnection = Приложение(Соединение)
Хотя объекту Recordset по-прежнему необходимо создать соединение, на данный момент создание выполняется в высокооптимизированных условиях. В результате накладные расходы страницы снизились еще на 23% по сравнению с предыдущим тестом, а время отображения одной записи, как и ожидалось, существенно не изменилось.
Поэтому наше второе правило таково:
lЕсли вы используете только один набор записей, напрямую назначьте строку подключения свойству ActiveConnection.
Затем мы проверяем, действуют ли приведенные выше правила, когда на странице используется несколько наборов записей. Чтобы проверить эту ситуацию, мы вводим цикл FOR, который повторяет предыдущий пример 10 раз. В этом тесте мы рассмотрим три варианта:
Сначала, как показано в ADO__04.asp, объект Connection устанавливается и уничтожается в каждом цикле:
Скопируйте код кода следующим образом:
Дим я
Для я = от 1 до 10
Установите objConn = Server.CreateObject(ADODB.Connection)
objConn.Открыть приложение (Conn)
Установите objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Открыть приложение (SQL)
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'написать заголовки
...
'записать данные
...
Конец, если
objRS.Close
Установить objRS = Ничего
objConn.Close
Установить objConn = Ничего
Следующий
Во-вторых, как показано в ADO__05.asp, создайте объект Connection вне цикла и поделитесь этим объектом со всеми наборами записей:
Скопируйте код кода следующим образом:
Установите objConn = Server.CreateObject(ADODB.Connection)
objConn.Открыть приложение (Conn)
Дим я
Для я = от 1 до 10
Установите objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Открыть приложение (SQL)
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'написать заголовки
...
'записать данные
...
Конец, если
objRS.Close
Установить objRS = Ничего
Следующий
objConn.Close
Установить objConn = Ничего
В-третьих, как показано в ADO__06.asp, назначьте строку подключения свойству ActiveConnection в каждом цикле:
Скопируйте код кода следующим образом:
Дим я
Для я = от 1 до 10
Установите objRS = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = Приложение(Соединение)
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Открыть приложение (SQL)
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'написать заголовки
...
'записать данные
...
Конец, если
objRS.Close
Установить objRS = Ничего
Следующий
Как мы можем догадаться, создание и удаление объектов соединения внутри цикла — наименее эффективный способ. Однако удивительно, что присвоение строки подключения непосредственно свойству ActiveConnection внутри цикла происходит лишь немного медленнее, чем совместное использование одного объекта Connection.
Тем не менее, третье правило должно звучать так:
lЕсли на одной странице используется несколько наборов записей, создайте один объект подключения и поделитесь им через свойство ActiveConnection.
6. Какой тип курсора и метод блокировки записи являются наиболее эффективными?
До сих пор во всех тестах мы использовали только прямые курсоры для доступа к набору записей. Существует три типа курсоров, предоставляемых ADO для наборов записей: статические курсоры с прокруткой, динамические курсоры с прокруткой и курсоры набора ключей. Каждый курсор предоставляет различные функции, например, доступ к предыдущей и следующей записи, возможность просмотра изменений данных, выполненных другими программами, и т. д. Однако подробное обсуждение функций каждого типа курсоров выходит за рамки этой статьи. В следующей таблице представлен сравнительный анализ различных типов курсоров.
Все другие типы курсоров требуют дополнительных затрат по сравнению с курсорами, предназначенными только для прямого перемещения, и эти курсоры обычно работают медленнее внутри циклов. Поэтому мы хотели бы поделиться с вами следующим предостережением: Никогда не думайте так — ну, иногда я буду использовать динамические курсоры, поэтому я всегда буду использовать этот курсор.
То же самое относится и к выбору метода блокировки записи. В предыдущем тесте использовался только метод блокировки только для чтения, но есть еще три метода: консервативный, открытый и открытая пакетная обработка. Как и типы курсоров, эти методы блокировки предоставляют различные функциональные возможности и контроль над работой с данными набора записей.
Мы приходим к следующим правилам:
lИспользуйте самый простой тип курсора и метод блокировки записи, подходящий для данной задачи.
7. Какой метод лучше всего использовать для извлечения набора записей?
До сих пор мы извлекали наборы записей путем создания объектов Recordset, но ADO также предоставляет косвенные методы извлечения наборов записей. Следующий тест сравнивает ADO__03.asp и создание набора записей непосредственно из объекта Connection (CONN_01.asp):
Скопируйте код кода следующим образом:
Установите objConn = Server.CreateObject(ADODB.Connection)
objConn.Открыть приложение (Conn)
Установите objRS = objConn.Execute(Application(SQL))
Вы можете видеть, что накладные расходы страницы немного увеличились, а время отображения одной записи не изменилось.
Давайте посмотрим на создание объекта набора записей (CMD__02.asp) непосредственно из объекта Command:
Скопируйте код кода следующим образом:
Установите objCmd = Server.CreateObject(ADODB.Command)
objCmd.ActiveConnection = Приложение(Соединение)
objCmd.CommandText = Приложение (SQL)
Установите objRS = objCmd.Execute
Аналогичным образом, немного увеличиваются затраты на страницу без существенного изменения времени отображения одной записи. Разница в производительности между двумя последними методами невелика, но нам нужно рассмотреть важный вопрос.
Создавая набор записей с помощью класса Recordset, мы можем управлять обработкой набора записей с максимальной гибкостью. Поскольку последние два метода не обеспечивают превосходной производительности, мы в основном рассматриваем тип курсора и метод блокировки записи, возвращаемый по умолчанию. В некоторых случаях значение по умолчанию не обязательно является самым идеальным.
Поэтому, если нет особых причин выбирать между двумя последними способами, рекомендуем учитывать следующие правила:
l Создайте экземпляр набора записей с помощью класса ADODB.Recordset, чтобы добиться максимальной производительности и гибкости.
8. Должен ли я использовать локальный набор записей?
ADO позволяет использовать локальные (клиентские) наборы записей. В это время запрос извлечет все данные из набора записей. После завершения запроса соединение можно немедленно закрыть и использовать локальные курсоры для доступа к данным. будущее, которое обеспечивает удобство разрыва соединения. Использование локальных наборов записей важно для доступа к удаленным службам обработки данных, которые требуют использования данных в автономном режиме, но будет ли это полезно и для обычных приложений?
Затем мы добавляем атрибут CursorLocation и закрываем соединение (CLIENT1.asp) после открытия набора записей:
Скопируйте код кода следующим образом:
Установите objRS = Server.CreateObject(ADODB.Recordset)
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = Приложение(Соединение)
objRS.LockType = 1?'
objRS.Открыть приложение (SQL)
objRS.ActiveConnection = Ничего
Теоретически этот подход повышает эффективность по двум причинам: во-первых, он позволяет избежать повторного запроса данных через соединение при перемещении между записями, во-вторых, он упрощает требования к ресурсам. Однако из приведенной выше таблицы видно, что использование локального набора записей явно не поможет повысить эффективность. Это может быть связано с тем, что при использовании локального набора записей курсор всегда становится статическим типом, независимо от настроек программы.
Правило 6 звучит следующим образом:
lЭтого следует избегать, если только локализация набора записей действительно не требуется.
10. Какой метод наиболее эффективно использовать для ссылки на значения полей в наборе записей?
10.1 Тестирование
До сих пор мы ссылались на значения полей в наборе записей по имени. Поскольку этот метод требует каждый раз находить соответствующее поле, он не очень эффективен. Чтобы продемонстрировать это, в следующем тесте мы ссылаемся на значение поля по его индексу в коллекции (ADO__08.asp):
Скопируйте код кода следующим образом:
'записать данные
Делайте, пока не objRS.EOF
Ответ.Запись(_
<ТР> & _
<TD> & objRS(0) & </TD> & _
<TD> & objRS(1) & </TD> & _
<TD> & objRS(2) & </TD> & _
<TD> & objRS(3) & </TD> & _
<TD> & objRS(4) & </TD> & _
<TD> & objRS(5) & </TD> & _
<TD> & objRS(6) & </TD> & _
</TR> _
)
objRS.MoveNext
Петля
Как и ожидалось, также произошли небольшие изменения в служебных данных страницы (возможно, из-за небольшого сокращения кода). Однако улучшение времени отображения при таком подходе весьма заметно.
В следующем тесте мы привязываем все поля к переменным индивидуально (ADO__09.asp):
Скопируйте код кода следующим образом:
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'написать заголовки
...
Тусклый флд0
Тусклый флд1
Тусклый флд2
Тусклый флд3
Тусклый флд4
Тусклый флд5
Тусклый флд6
Установить fld0 = objRS(0)
Установите fld1 = objRS(1)
Установите fld2 = objRS(2)
Установите fld3 = objRS(3)
Установите fld4 = objRS(4)
Установите fld5 = objRS(5)
Установите fld6 = objRS(6)
'записать данные
Делайте, пока не objRS.EOF
Ответ.Запись(_
<ТР> & _
<TD> & fld0 & </TD> & _
<TD> & fld1 & </TD> & _
<TD> & fld2 & </TD> & _
<TD> & fld3 & </TD> & _
<TD> & fld4 & </TD> & _
<TD> & fld5 & </TD> & _
<TD> & fld6 & </TD> & _
</TR> _
)
objRS.MoveNext
Петля
Установить fld0 = Ничего
Установить fld1 = Ничего
Установить fld2 = Ничего
Установить fld3 = Ничего
Установить fld4 = Ничего
Установить fld5 = Ничего
Установить fld6 = Ничего
Ответ.Запись(</TABLE>)
Конец, если
Это лучший рекорд на данный момент. Обратите внимание, что время отображения одной записи сокращено до менее 0,45 миллисекунды.
Все приведенные выше сценарии требуют некоторого понимания конструкции набора результирующих записей. Например, мы используем имена полей непосредственно в заголовках столбцов, чтобы ссылаться на каждое значение поля индивидуально. В следующем тесте путем обхода коллекции полей получаются не только данные полей, но и заголовки полей. Это более динамичное решение (ADO__10.asp).
Скопируйте код кода следующим образом:
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
'запись заголовков Response.Write(<TABLE BORDER=1><TR>)
Для каждого objFld в objRS.Fields
Response.Write(<TH> & objFld.name & </TH>)
Следующий
Ответ.Запись(</TR>)
'записать данные
Делайте, пока не objRS.EOF
Ответ.Запись(<TR>)
Для каждого objFld в objRS.Fields
? Response.Write(<TD> & objFld.value & </TD>)
Следующий
Ответ.Запись(</TR>)
objRS.MoveNext
Петля
Ответ.Запись(</TABLE>)
Конец, если
Как видите, производительность кода снизилась, но он все равно быстрее, чем ADO__07.asp.
Следующий тестовый пример представляет собой компромисс двух предыдущих методов. Мы продолжим поддерживать динамическую функцию, одновременно улучшая производительность за счет сохранения ссылок на поля в динамически выделяемых массивах:
Скопируйте код кода следующим образом:
Если objRS.EOF Тогда
Response.Write(записи не найдены)
Еще
Дим флдКаунт
fldCount = objRS.Fields.Count
Тусклый флд()
Редим флд(fldCount)
Дим я
Для i = 0 до fldCount-1
Установите fld(i) = objRS(i)
Следующий
'написать заголовки
Response.Write(<TABLE BORDER=1><TR>) Для i = 0 до fldCount-1
Response.Write(<TH> & fld(i).name & </TH>)
Следующий
Ответ.Запись(</TR>)
'записать данные
Делайте, пока не objRS.EOF
Ответ.Запись(<TR>)
Для i = 0 до fldCount-1
Response.Write(<TD> & fld(i) & </TD>)
Следующий
Ответ.Запись(</TR>)
objRS.MoveNext
Петля
Для i = 0 до fldCount-1
Установить fld(i) = Ничего
Следующий
Ответ.Запись(</TABLE>)
Конец, если
Хотя он и не превосходит предыдущий лучший результат, он быстрее первых нескольких примеров и имеет преимущество динамической обработки любого набора записей.
По сравнению с предыдущим тестовым кодом следующий тестовый код был существенно изменен. Он использует метод GetRows объекта Recordset для заполнения массива для итерации по данным, а не напрямую обращается к самому Recordset. Обратите внимание, что для набора записей сразу после вызова GetRows устанавливается значение Nothing, что означает, что системные ресурсы освобождаются как можно скорее. Также обратите внимание, что первое измерение массива представляет поля, а второе измерение — строки (ADO__12.asp).
Скопируйте код кода следующим образом:
Если objRS.EOF Тогда
Response.Write(записи не найдены)
objRS.Close
Установить objRS = Ничего
Еще
'написать заголовки
...
'установить массив
Дим-прибытие
arrRS = objRS.GetRows
'раньше закрыть набор записей
objRS.Close
Установить objRS = Ничего
'записать данные
ДимнумРовс
ДимнумФлдс
Тусклый ряд
Тусклый флд
numFlds = Ubound(arrRS, 1)
numRows = Ubound(arrRS, 2)
Для строки = от 0 до numRows
Ответ.Запись(<TR>)
Для fld = от 0 до numFlds
Response.Write(<TD> & arrRS(fld, row) & </TD>)
Следующий
Ответ.Запись(</TR>)
Следующий
Ответ.Запись(</TABLE>)
Конец, если
При использовании метода GetRows весь набор записей извлекается в массив. Хотя проблемы с ресурсами могут возникнуть, когда набор записей чрезвычайно велик, доступ к данным в цикле действительно происходит быстрее, поскольку вызовы функций, таких как MoveNext, и проверка EOF отменяются.
За скорость приходится платить, теперь метаданные набора записей теряются. Чтобы решить эту проблему, мы можем извлечь информацию заголовка из объекта набора записей перед вызовом GetRows, кроме того, тип данных и другую информацию также можно извлечь заранее; Также обратите внимание, что преимущество в производительности при тестировании возникает только в том случае, если набор записей больше.
В последнем тесте этого набора мы используем метод GetString набора записей. Метод GetString извлекает весь набор записей в большую строку и позволяет указать разделитель (ADO__13.asp):
Скопируйте код кода следующим образом:
Если objRS.EOF Тогда
Response.Write(записи не найдены)
objRS.Close
Установить objRS = Ничего
Еще
'написать заголовки
...
'установить массив
Тусклая стрТаблица
strTable = objRS.GetString (2, , </TD><TD>, </TD></TR><TR><TD>)
'закрыть набор записей раньше времени
objRS.Close
Установить objRS = Ничего
Response.Write(strTable & </TD></TR></TABLE>)
Конец, если