the mine universe

среда, 14 октября 2009 г.

SQL Server Profiler Library

Неделю назад я рассказывал как можно без побочных эффектов использовать SQL-сервер в true unit-tests. Теперь я расскажу где использовал предыдущий пост. Сегодня предлагаю интегрировать в свои продукты средства трассировки и профилирования встроенные в SQL-сервер. И в MSDE 2000, и в SQL Express 2005/2005 в том числе.

Когда речь идет о профилировании часто самое сложное - найти бутылочное горлышко. Хуже всего то, что как правило в среде разработки и тестирования система ведет себя совершенно не так в production environment. Мне в случае проблем с производительностью у какого нибудь заказчика приходится "отмазываться" простым вопросом, на который закзачик ответить толком не может. Я прошу описать в цифрах "профиль загрузки системы". Заказчик на какое-то время впадает в ступор, тем не менее проблема остается - а это не очень приятно.

Могу так же подтвердить из своего опыта, что проблема поиска бутылочного горлышка случается не только с тиражируемыми коробочными продуктами, но и с inhouse-системами (внутренняя самостоятельная разработка для одной компании)

Раньше я рассказывал как бороться с трафиком в на платформе WCF. Сегодня мой подопытный - IOPS. IOPS всегда были бутылочным горлышком в большинстве случаев. Понятно что диск намного медленнее работает чем память и CPU. Хуже другое:

  • Масштабирование диска существенно дороже масштабирования RAM и CPU. Для клиент-серверных системы CPU и память наращиваются совсем просто – добавлением в кластер сервера приложений еще одного узла.
  • Индустрия и технология производства дисков уверенно хранит показатель IOPS примерно на уровне 10-ти летней давности. Да, емкость и скорость последовательного чтения выросли на два порядка. А сколько вырос IOPS? В три раза? Всего-то :( Конечно последнее справедливо если закрыть глаза на новые SSD накопители с многоканальным контроллером памяти, например Intel X25 G2.

КПРР и структура журнала трассировки

  • Текст sql-команды и со значениями всех параметров. Если бы я сейчас рассказывал презентацию, а не щелкал по клавишам, сейчас бы сказал “WOW! Ух-ты!”. Значения параметров сюда попадают ав-то-ма-ти-чес-ки.
  • Идентификаторы подключения к SQL-серверу
  • Количественные показатели использованных ресурсов: CPU, Duration, Reads, Writes. Вокруг них проходят любые занятия профилированием.

Любые поля журнала можно отключать за ненадобностью, но в библиотеке не предусмотрено отключения “Количественных показателей использованных ресурсов”. Здесь и далее выражение в кавычках - КПРР. Любые поля журнала трассировки можно и нужно отключать в зависимости от сценария использования за ненадобностью.

Идентификация целевой области наблюдения

Сессия трассировки без фильтрации включает все команды всех приложений, исполненных sql сервером за время сеанса трассировки. Так устроен MS SQL Server. Это плохо, хотя иногда и хорошо. Но филтьтр по контексту нагрузки на SQL Server все же есть. И это безулословно хорошая фича. И "на стороне" SQL сервера и на клиенте есть хорошая возможность фильтровать команды на “свои” и “чужие”. Вот параметры фильтра:

  • Application Name (определяется строкой подключения к серверу)
  • Database (определяется по строке подключения к серверу, фактическая БД с которой работает запрос, к этому полю отношения имеет мало)
  • Client Host (обычно на клиенте эта строка равна Environment.MachineName)
  • Client Process (на клиенте доступно с помощью Process.GetCurrentProcess().Id)
  • Login (определяется строкой подключения к серверу)
  • Server Process (на клиенте доступно в виде функции @@spid)

Сценарии использования

  • Получить суммы КПРР, сгруппированные по типам удаленных вызовов? Одна сессия трассировки на всю систему. В ApplicationName включить имя action wcf-метода (или Request.Uri web-приложения).
  • Получить полную подробную трассировку на каждый экземпляр удаленного вызова? На каждый unit of work отдельная сессия трассировки.
  • Получить распределение загрузки ресурсов SQL сервера между своим продуктом и сторонними приложениями? Пожалуйста - единственная сессия трассирови на всю систему. В ApplicationName уникальное и хорошо известный идентификатор своего продукта|системы.
  • Получить трассировку на каждую SQL команду? Одна сессия трассировки на каждую команду.

Последний сценарий – самый простой. Последний сценарий дает самый подробный отчет. Почему же нужны еще другие сценарии? Ответ – производительность.

Отчет по журналу трассировки

Раз я заговорил об трасисровке на продакшене, то и в библиотеке реализовал три способа вычитывания отчета трассировки:

  • Детальный, как в SQL Server Profiler. Самый полный отчет - весь журнал вычитывается строчка за строчкой.
  • Суммы по группам. "КПРР" суммируются по интересным группам.
  • Тотальная сумма "КПРР" - количество запросов и четыре суммы использованных ресурсов

Производительность

Я взял в качестве подопытного кода самый легкий запрос: SELECT Null

  • Первая колонка – кол-во конкурентных потоков.
  • Commands – кол0во выполненных команд
  • Duration – время затраченное на выполнение. Оно включает старт и стоп сессий трассировки и не включает время на создание и уничтожение конкурентных потоков.
  • CPU – процессорное время использованное на “клиенте”.

Потребление ресурсов самого SQL-сервера здесь не интересно. Интересно другое - я накткулся на форуме на интересный термин профилирования: Оказывается можно различать серверную трассировку, она же real server side trace. И клиентскую трассировку. Под клиентской чувак Tibor (MVP) понимает сеанс трассировки выполняемый под SQL Server Profiler с записью журнала в файл или БД. Вот эта библиотека, о которой я сейчас рассказываю - это real server side tracing.

Два важных вывода:

Сама по себе трассировка  на производительность влияет незначительно. А вот сессия трассировки неприлично тормозит на два порядка в сценарии одна сессия трассировки на один запрос. Но это всего лишь пол беды. Хуже то что пуск и остановка сессии трассировки не масштабируется по ядрам процессора.

Использование RAM-диска драматически улучшает производительность инстанцирования сессии трассировки. Хотя масштабирование по ядрам процессора по прежнему отсутствует.

Дисклаймер юнит-тестов

Тесты проверяют только библиотеку, но не SQL сервер и не трассировку. Поэтому в тестах всего два ценных сценария:

  • Ловится вызов хранимки. в unit-тесте проверяется что захвачена именно sp_executesql с нашим кодом. и код И вызов хранимой процедуры и любая команда с параметрами попадают в журнал трассировки.
  • Ловится batch-код.

Ярлыки (Tags)