Поделиться через


Ускорение SQL

Оптимизация вызовов базы данных с помощью Tier Interaction Profiling

Марк Фридман

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

Профилирование взаимодействия уровней (Tier Interaction Profiling, TIP) призвано помочь вам разобраться в производительности уровня данных, на который опирается все приложение. TIP — новое средство в инструментарии профилирования Visual Studio, которое измеряет (и генерирует отчеты) длительность задержек, вызываемых обращением к уровню данных приложениями .NET Framework, при ожидании выполнения синхронных вызовов, адресованных совместимым с ADO.NET базам данных. В случае приложений, для которых важна скорость отклика и которые часто обращаются к базам данных, TIP помогает понять, какие запросы данных вносят наибольший вклад в задержки ответов.

В этой статье я познакомлю вас с TIP и продемонстрирую его средства отчетности. Мы также обсудим технологию оснащения, на которую полагается TIP, и рассмотрим некоторые рекомендации по эффективному применению TIP для диагностики проблем производительности, связанных с обращениями к базам данных. Я пошагово покажу, как использовать TIP, на примере двухуровневого веб-приложения ASP.NET, интенсивно работающего с данными Microsoft SQL Server по технологии LINQ to SQL. Наконец, я расскажу, как дополнить данные TIP по производительности, используя стандартные средства SQL Administrator, чтобы получить еще более глубокое представление о производительности уровня данных.

Приступаем к работе с TIP

TIP динамически добавляет код оснащения (instrumentation code) для измерения длительности вызовов уровня данных в вашем приложении в сеансе профилирования. Средства профилирования Visual Studio доступны в редакциях Visual Studio 2010 Premium и Visual Studio 2010 Ultimate.

Чтобы начать сеанс профилирования, можно выбрать Launch Performance Wizard из меню Analyze, выбрать Start Performance Analysis из меню Debug или нажать комбинацию клавиш Alt+F2. На первой странице Performance Wizard предлагается выбрать метод профилирования.

TIP можно использовать с любым методом профилирования (выборка, оснащение, память или параллельная обработка), но по умолчанию оно не включается. Перед тем как разрешить использование TIP, вы должны сначала сбросить флажок Launch profiling after the wizard finishes на третьей странице Performance Wizard. (Поскольку TIP пока не включен, вы не готовы запускать свое приложение и начинать профилирование.) Советую изначально указать выборку в качестве метода профилирования, особенно если вас больше всего интересует информацию по взаимодействию с уровнем данных. Это связано в основном с тем, что выборка оказывает наименьшее влияние на производительность вашего приложения.

Для включения сбора данных TIP перейдите в Performance Wizard в Performance Session, только что созданный в окне Performance Explorer, и щелкните правой кнопкой мыши, чтобы увидеть его свойства. В диалоге свойств выберите вкладку Tier Interactions и установите флажок Enable tier interaction profiling. Щелкните кнопку OK для закрытия диалога. Теперь, когда TIP включен, вы готовы начать профилирование своего приложения.

Для запуска реального сеанса профилирования щелкните кнопку Launch with Profiling на панели инструментов в окне Performance Explorer.

Полные инструкции по включению TIP в Visual Studio см. в статье Хабиба Хейдариана (Habib Heydarian) «Walkthrough: Using the Tier Interaction Profiler in Visual Studio Team System 2010» в блоге https://blogs.msdn.com/b/habibh/archive/2009/06/30/walkthrough-using-the-tier-interaction-profiler-in-visual-studio-team-system-2010.aspx.

Как TIP замеряет производительность

TIP вставляет код в ваше приложение в течение сеанса профилирования, замеряющий время вызовов уровня данных ADO.NET, используемого приложением. Когда TIP активен, Visual Studio Profiler анализирует MSIL-код (Microsoft intermediate language) вашего решения и ищет ссылки на ADO.NET-функции. Перед вызовом JIT-компилятора для генерации неуправляемого кода, выполняемого приложением, средство профилирования вставляет инструкции, добавляющие оснащение в ключевые методы ADO.NET. Этот код оснащения отслеживает время, затраченное каждым ADO.NET-вызовом.

При выполнении приложения TIP захватывает и записывает данные о длительности любого ADO.NET-вызова, а также захватывает текстовую копию команд, использованных при обращении к базе данных. И так собираются все временные (с ударением на последнем слоге) данные для всех обращений к базе данных с использованием синхронных методов ADO.NET-классов, в том числе API-интерфейсов SQL, OLE DB, Open Database Connectivity (ODBC) и SQL Server Compact (SQL CE). TIP также захватывает временные данные, если ваше приложение использует LINQ to SQL или Entity Framework API для доступа к базам данных SQL.

Временные данные хранятся наряду с другими данными, собираемыми в ходе сеанса профилирования, в файле Visual Studio Profiler (.vsp). Поскольку приложение, инициирующее вызов к внешней базе данных, выполняет внепроцессный вызов, инструкции, добавляемые TIP для оснащения, очень слабо влияют на общую производительность приложения.

Оптимизация для большей производительности

Распространенный проектировочный шаблон включает разделение веб-приложения на презентационный уровень, уровень бизнес-логики (прикладной логики) и уровень данных. Эта парадигма проектирования ведет к разбиению приложения на компоненты, что способствует повышению надежности, расширяемости и масштабируемости. Многоуровневое приложение обращается к своему уровню данных через компоненты уровня бизнес-логики, которые ссылаются на сущности данных как на строки и поля в соответствующем наборе таблиц. Как база данных наподобие SQL Server поддерживает физические данные, связанные с таблицами базы данных, — этот механизм прозрачен для вашего приложения по самой его архитектуре.

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

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

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

В многоуровневых приложениях, взаимодействующих с внешней базой данных, компонент базы данных зачастую является основным «вкладчиком» в общее время ответа приложения. Средства профилирования Visual Studio поддерживают разнообразные методы профилирования, в том числе выборку (sampling), оснащение (instrumentation), выделение памяти (memory allocation) и параллельную обработку (concurrency), но ни один из этих методов обычно ничем не помогает в выявлении проблем производительности, связанных с доступом к внешней базе данных, без информации TIP.

Данные TIP позволяют углубленно анализировать задержки, связанные с обращением к базе данных, и понять, почему они возникают. В сочетании с другими средствами анализа производительности, предоставляемыми поставщиком вашей СУБД, вы начнете понимать, что можно сделать для повышения производительности приложения, которая сильно зависит от скорости работы базы данных.

Поскольку TIP добавляет оснащение в код приложения, временные данные, связанные с командами базы данных, можно собирать независимо от того, где физически расположен экземпляр базы данных. Такие данные можно собирать, например, для внепроцессных вызовов экземпляра SQL Server, физически размещенного на той же машине, что и приложение, — это типичный вариант при модульном тестировании. Когда то же самое приложение готово к тестированию на интеграцию или к нагрузочному тестированию с использованием экземпляра SQL Server, расположенного на отдельной физической машине, TIP может собирать данные и в такой конфигурации. Фактически замеры TIP позволяют вам сравнивать производительность приложения в этих двух конфигурациях.

TIP дает возможность сравнивать влияние многих параметров оптимизации и скорости работы внешней базы данных, в том числе конфигурации кеш-памяти, физических устройств хранилища данных, конфигурации разделов базы данных, индексации базы данных и структуры ее таблиц. Кроме того, вы можете напрямую измерять влияние на производительность экземпляра SQL Server, выполняемого в виртуальной машине.

Основные сведения об отчетах TIP

По завершении сеанса профилирования с активированным TIP временные данные, сопоставленные с любым обращением вашего приложения к его ADO.NET-уровню данных, суммируются в представлении Tier Interactions. На рис. 1 показан пример, когда собираются данные TIP и в сеансе профилирования наблюдается активность, связанная с ADO.NET.

image: A Visual Studio Profiler Tier Interaction Report

Рис. 1. Отчет Tier Interaction Visual Studio Profiler

Верхняя половина отчета — это сводка собранных данных профилирования. Для приложений ASP.NET представление структурируется по URL. В отчете информация по времени ответов серверной стороны на запросы GET от веб-приложения группируется по URL.

Под уровнем приложения в отчете показывается каждое соединение с уровнем базы данных (в качестве которой в этом примере использовался образец базы данных AdventureWorks). TIP замеряет и сообщает о серверной части времени обработки запросов ASP.NET, связанных с синхронными вызовами базы данных через ADO.NET. В этом примере появляются три сводные строки, каждая из которых сводит в табличную форму активность базы данных, связанную с тремя разными ASP.NET-страницами на профилируемом веб-сайте. Для каждой идентифицированной ASP.NET-страницы сообщается количество запросов ASP.NET, обработанных в сеансе профилирования, и время ответов от сервера для каждого сгенерированного сообщения ответа.

В дополнительных сводных строках показываются данные по времени ответов для других GET-запросов, включая запросы таблиц стилей, Javascript-кода и изображений, на которые ссылаются страницы. Любые вызовы базы данные, которые средству профилирования не удалось сопоставить с конкретным запросом ASP.NET, группируются в категории Other Requests.

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

Под сводной строкой каждой веб-страницы размещается одна сводная строка, в которой сообщается о количестве синхронных запросов базы данных (в ходе ASP.NET-обработки), организованных по соединению с базой данных. В этом примере видно, что шесть запросов ASP.NET к Customer­Query.aspx были переданы по единственному соединению с базой данных. Эти шесть запросов потребовали на обработку на серверной стороне итого 0,959 секунды при среднем времени ответа 160 мс. Эти запросы инициировали 12 SQL-запросов, на выполнение которых ушло приблизительно 45 мс. Ожидание запросов к базе данных заняло лишь около 5% от всего времени, понадобившегося на генерацию сообщений ответов для этой веб-страницы.

Если вы выберете одну из сводных строк по соединению с базой данных, в нижней половине представления Tier Interactions будут показаны конкретные SQL-команды, выданные приложением. SQL-команды группируются по тексту команд и сортируются по прошедшему времени внутри группы страниц.

В этом примере одна SQL-команда выдавалась три раза, другая — шесть раз, третья — три раза. В режиме просмотра подробностей (detail view) время выполнения каждого запроса, изначально свернутое в одну общую строку, показывается по отдельности. Вы можете посмотреть общее истекшее время, среднее значение по всем экземплярам команды, а также минимальную и максимальную задержки, наблюдавшиеся для каждого запроса.

Если дважды щелкнуть строку подробностей SQL-команды, в окне Database Command Text будет отображен полный текст выданной SQL-команды. Это реальная команда, переданная приложением базе данных через интерфейс ADO.NET в процессе выполнения. Если запрос потребовал выполнения хранимой процедуры, показывается, какая хранимая процедура была вызвана.

Пример LINQ to SQL

Давайте рассмотрим простой пример использования TIP для анализа приложения ASP.NET, которое интенсивно работает с информацией в базе данных.

TIP может быть особенно полезным в случае приложений, использующих LINQ to SQL для доступа к данным, которые хранятся во внешней базе данных SQL Server, так как LINQ создает для разработчика еще один уровень абстракции от физической базы данных и ее рабочих характеристик. В случае LINQ to SQL диаграммы Entity:Relationship (E:R), создаваемые вами в Object Relational Designer, приводят к генерации классов, которые потом используются Visual Studio в качестве шаблонов для автоматического создания синтаксически корректных SQL-команд.

Поскольку технология LINQ to SQL исключает большую часть кодирования непосредственно на языке SQL и проста в использовании, она также маскирует важные факторы, влияющие на производительность и связанные со структурой базы данных, конфигурацией и оптимизацией. Как иллюстрирует этот пример, применяя LINQ, легко создать сложный запрос, который объединяет множество таблиц без учета последствий для производительности.

С помощью TIP вы можете увидеть настоящий текст SQL-команд, генерируемый LINQ to SQL, и собирать замеры по скорости выполнения этих SQL-запросов. Располагая текстом SQL-команд, вы можете потом задействовать другие средства тонкой настройки базы данных, которые помогут вам лучше понять последствия для производительности любой конкретной операции LINQ to SQL.

Мой пример — это приложение Web Forms, которое запрашивает таблицы Adventure­Works Sales.Customer, используя указанный идентификатор клиента (customer) для получения истории его заказов. Таблицы AdventureWorks, участвующие в этом запросе, включают Customer, SalesOrderHeader, Sales­OrderDetail и StateProvince, как показано в представлении Object Relational Designer на рис. 2.

image: The AdventureWorks Tables Used to Query Sales.Customer Information

Рис. 2. Таблицы AdventureWorks, используемые для запроса информации Sales.Customer

Если вы хотите заодно выводить информацию об адресах обычной и электронной почты клиента, вам понадобится еще и доступ к таблицам Customer­Address, Address и Contact. Как видно в Object Relational Designer, таблицы AdventureWorks содержат основной и внешний ключи, такие как CustomerID, SalesOrder и ContactID, позволяющие логически присоединять эти таблицы.

Код на C#, создающий запрос по клиенту из AdventureWorks с применением LINQ to SQL, представлен на рис. 3. В данном случае custid — это значение запрошенного CustomerID. Этот запрос возвращает набор customeryquery, который содержит единственную строку с полями, перечисленными в блоке select new.

Рис. 3. Запрос по клиенту LINQ to SQL

var customerquery = 
  from customers in db.Customers
  from custaddrs in db.CustomerAddresses
  from addrs in db.Addresses
  where (customers.CustomerID == custid &&
         customers.CustomerID == custaddrs.CustomerID &&
         custaddrs.AddressID == addrs.AddressID)

  select new {
    customers.CustomerID,
    customers.CustomerType,
    addrs.AddressLine1,
    addrs.AddressLine2,
    addrs.City,
    addrs.StateProvince,
    addrs.PostalCode,
    customers.TerritoryID
  };

После этого customeryquery можно связать с элементом управления в веб-странице ASP.NET:

DetailsView1.DataSource = customerquery;
DetailsView1.DataBind();

Теперь я могу создать запрос для получения истории заказов по конкретному клиенту:

var orderquery = 
  from orderhdr in db.SalesOrderHeaders
  where (orderhdr.CustomerID == custid)
  orderby orderhdr.OrderDate
  select new {
    Date = orderhdr.OrderDate.ToShortDateString(),
    orderhdr.AccountNumber,
    InvoiceNo = orderhdr.SalesOrderID,
    orderhdr.TotalDue
  };

После выполнения этой операции LINQ to SQL набор orderquery будет содержать строку, соответствующую каждой строке в таблице OrderHdr, сопоставленной с указанным Customer ID.В наборе orderquery будет содержаться несколько строк, если история заказов по данному клиенту указывает, что было несколько транзакций продаж.

На первый взгляд эти запросы кажутся достаточно простыми. Но, используя TIP, вы начнете понимать последствия для производительности кажущихся простыми операций LINQ to SQL.

Применение данных TIP для оптимизации

Давайте повнимательнее приглядимся к customerquery. В период выполнения LINQ to SQL принимает логические операции SELECT, подразумеваемые в LINQ-выражении, и на их основе генерирует допустимую SQL-команду, которая объединяет данные из четырех таблиц AdventureWorks: Customers, Customer­Addresses, Addresses и статической StateProvince. Вы не видите этого в приведенном здесь коде LINQ to SQL.

Когда вы запускаете этот код с подключенным Visual Studio Profiler, оснащение TIP сообщает, сколько раз выполнялся этот запрос, и замеряет время задержки выполнения веб-страницы. Это фактически та операция, которая выполнялась шесть раз в сеансе профилирования, проиллюстрированного на рис. 1.

Кроме того, как вы уже видели, SQL-команда, сгенерированная кодом LINQ to SQL, также доступна, когда профилирование приложения закончено. На рис. 4 показана реальная SQL-команда для этой операции.

Рис. 4. SQL-команда для customerquery

SELECT [t0].[CustomerID], [t0].[CustomerType], [t2].[AddressLine1], [t2].[AddressLine2], [t2].[City], [t3].[StateProvinceID], [t3].[StateProvinceCode], [t3].[CountryRegionCode], [t3].[IsOnlyStateProvinceFlag], [t3].[Name], [t3].[TerritoryID], [t3].[rowguid], [t3].[ModifiedDate], [t2].[PostalCode], [t0].[TerritoryID] AS [TerritoryID2]
FROM [Sales].[Customer] AS [t0]
CROSS JOIN [Sales].[CustomerAddress] AS [t1]
CROSS JOIN [Person].[Address] AS [t2]
INNER JOIN [Person].[StateProvince] AS [t3] ON [t3].[StateProvinceID] = [t2].[StateProvinceID]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = [t1].[CustomerID]) AND ([t1].[AddressID] = [t2].[AddressID])

Заметьте, что в текст SQL-команды включается лексема (обозначенная здесь как «@p0»), которая представляет параметр идентификатора клиента, передаваемый LINQ в запросе.

Теперь, располагая текстом реальной SQL-команды, сгенерированной LINQ, можно разобраться в том, как влияет структура базы данных на производительность запроса.

Вы можете выполнить эту SQL-команду в SQL Server Management Studio и изучить ее план выполнения, как показано на рис. 5. Чтобы получить доступ к плану выполнения этого запроса, нужно добавить команду, которая указывает на соответствующую базу данных:

USE AdventureWorks ;
GO

Затем скопируйте текст SQL-команды из отчета TIP и не забудьте заменить лексему @p0 корректным CustomerID из базы данных. Затем запустите этот запрос-пример в SQL Server Management Studio и вы получите доступ к плану выполнения, который показывает, как оптимизатор запросов транслирует логический запрос в физический план выполнения.

image: The Execution Plan for the Example LINQ to SQL Operation

Рис. 5. План выполнения для примера операции LINQ to SQL

В этом примере план выполнения запроса показывает, что выражение SELECT, обращающееся к таблице Customer, использует кластерный индекс в поле CustomerID, которое возвращает ровно одну строку из таблицы. В SQL Server Management Studio можно задерживать курсор мыши на какой-либо операцией и просматривать ее свойства или выделять операцию и щелкать ее правой кнопкой мыши для открытия окна Properties. Таким способом вы можете пройти по всем оставшимся операциям, которые запрашивает данная команда. Каждое из трех последующих JOIN, дополняющих начальное выражение Customer SELECT, также обращается к таблице, используя ее кластерный индекс, и возвращает единственную уникальную строку.

Из этого исследования видно, что при обработке данного запроса приходится обращаться всего к четырем строкам, каждая из отдельной таблицы в базе данных AdventureWorks. Каждое обращение эффективно выполняется по уникальному основному ключу таблицы.

Аналогично вы можете использовать TIP, чтобы увидеть SQL-команду для кода orderquery и, вставив ее текст в SQL Server Management Studio, посмотреть ее план выполнения (рис. 6). Этот запрос обращается к единственной таблице OrderHdr, используя CustomerID как внешний ключ, поэтому ему нужеен доступ как к обычному, не кластерному индексу (ordinary nonclustered index), так и к кластерному индексу (clustered index) в SalesOrderHeaderID.

image: The Execution Plan for orderquery

Рис. 6. План выполнения для orderquery

Этот конкретный экземпляр запроса возвращает девять строк. Блок orderby в коде LINQ to SQL транслируется в SQL-блок ORDER BY, который влечет за собой дополнительную операцию Sort над каждым набором результатов от SELECT. По оценке SQL Server Plan Optimizer, эта операция вносит 40% в общие издержки выполнения запроса.

Выбор контекста профилирования

TIP рассчитан на то, чтобы дополнять существующие методы профилирования в Visual Studio для сбора специфических измерений при взаимодействиях с уровнем данных. Таким образом, TIP является вторичным механизмом сбора данных, и его нельзя использовать, не указав основной метод профилирования. Данные TIP можно собирать при профилировании с использованием выборки, оснащения или параллельной обработки для любого приложения, которое взаимодействует с уровнем данных через ADO.NET.

Учитывая необходимость выбора основного метода профилирования для приложения, в котором вам нужно собирать данные TIP, какой из них следует использовать? Давайте рассмотрим некоторые рекомендации по выбору основного метода профилирования.

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

Если же задержки на уровне данных не являются главной целью исследования производительности, выбирайте такой метод профилирования, который с максимальной вероятностью предоставит данные замеров, наиболее подходящие в текущем контексте. Например, если вы изучаете проблему, связанную с параллельным выполнением нескольких потоков, то собирайте данные параллельной обработки. А если вы анализируете проблему в приложении, интенсивно использующем процессор, собирайте данные выборки. Дополнительные соображения по выбору основного метода профилирования см. в статье How to: Choose Collection Methods».

Если вы еще не знакомы с кодом уровня данных, вам может понадобиться помощь от основного метода профилирования, чтобы найти код, из которого исходят ADO.NET-вызовы. TIP не захватывает стек вызовов, собирая временную информацию по синхронным внепроцессным ADO.NET-вызовам. Если вам нужно понять, откуда вызываются методы ADO.NET, наиболее полезными будут оснащенные профили. Данные выборки тоже могут помочь, но не с такой точностью, как оснащенный профиль.

Вы можете предпочесть сбор данных по конкуренции за ресурсы наряду с данными измерения по взаимодействию, но сбор данных конкуренции дает гораздо большие издержки, чем выборка, и данные по конкуренции вряд ли помогут вам определить, откуда исходят конкретные ADO.NET-вызовы. Анализу, требующему профилирования .NET Memory Allocation, которое обычно очень компактно, могут помешать замеры взаимодействия с уровнем данных.

Профили выборки

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

При наличии функций уровня данных, выполняемых вне текущего процесса, выборки инструкций выполнения, собранные в профиле выборки, как правило, не отражают времени, проведенного приложением в ожидании завершения синхронных вызовов через интерфейс ADO.NET. Пока исполняющий поток приложения ожидает завершения этих внепроцессных вызовов, он блокируется и никакие выборки выполнения применительно к нему не записываются. Поэтому при использовании выборки сбор данных TIP — лучший способ понять, какие задержки приложения связаны с синхронными вызовами уровня данных.

Оснащение, применяемое TIP, не захватывает стеки вызовов при сборе временных данных. Так что, если вы профилируете многоуровневое приложение и не слишком хорошо знакомы с его кодом, вам будет трудно точно определить, откуда исходят вызовы, адресованные уровню данных. Но профили выборки помогают идентифицировать, где в приложении выполняются вызовы интерфейсов ADO.NET. Если приложение часто вызывает интерфейсы ADO.NET, вам скорее всего удастся получить выборки, показывающие время, которое приложение провело в модулях ADO.NET, включая System.Data.dll и System.Data.Linq.dll.

Анализируя данные выборки и сравнивая их с замерами, относящимися к взаимодействию с уровнем данных, учитывайте, что, пока поток приложения блокируется в ожидании завершения синхронного вызова базы данных, никакие данные выборки для этого потока не собираются. Выборки, накопленные при выполнении, исключают внепроцессные задержки, которые явным образом измеряются TIP. Однако вы можете ожидать примерной корреляции между выборками выполнения, собранными в методах ADO.NET, и количеством ADO.NET-команд, отмеченных TIP. В таких случаях профили выборки часто помогают найти исходный код, откуда исходят ADO.NET-вызовы, собранные TIP.

Заметьте:если в приложении есть SQL-запросы, возвращающие большие наборы результатов, которые затем связываются с каким-либо элементом управления на форме, то вы скорее всего обнаружите значительное число выборок выполнения в методе DataBind этого элемента управления. Информация о том, какие методы DataBind появляются в профиле выборки, тоже может помочь в поиске исходного кода, откуда исходят ADO.NET-вызовы.

Оснащенные профили

При сборе оснащенных профилей временные данные для методов, записываемые средствами оснащения, уже включают любое время, проведенное в ожидании завершения внепроцессных вызовов в методе. Временные данные, записываемые в оснащенном профиле, собираются измерением времени на входе и выходе для каждого метода в приложении, выбранного для профилирования с оснащением. Такие данные для методов в приложении, которое взаимодействует с уровнем данных, неявно используя ADO.NET-вызовы, включают задержку в выполнении любого внепроцессного вызова.

Временные данные, собранные TIP, явным образом идентифицируют и предоставляют раздельные замеры внепроцессных задержек. Задержка, измеренная TIP, должна быть подмножеством общего времени, проведенного внутри метода, так как определяется в течение сеанса профилирования с оснащением. Понимая это, вы сможете сопоставить временные данные от TIP с аналогичными данными, собранными на уровне метода в оснащенном профиле, чтобы найти метод, из которого исходит вызов, адресованный уровню данных.

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

Больше данных, пожалуйста

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

Простое представление многоуровневого приложения, которое не охватывает все его взаимосвязанные уровни, никогда не даст вам полной картины производительности этого приложения. Как вы убедились, TIP может предоставить ключевые временные данные, которые нельзя получить иным способом. Как предполагает пример в этой статье, временные данные можно дополнять другими данными по производительности, получаемыми с помощью стандартных средств администрирования баз данных.

Марк Фридман - архитектор в отделе Visual Studio Ultimate корпорации Майкрософт. ОН является автором двух книг по производительности Windows и регулярно пишет в своем блоге о проблемах производительности по адресу blogs.msdn.com/ddperf/.

Выражаю благодарность следующим экспертам за рецензирование статьи: Дариуш Лакаб (Daryush Laqab) и Крис Шмич (Chris Schmich)