• Привет, Гость!
  • Войти
  • Регистрация
  • Записи
  • Форумы
  • Люди
  • Файлы
  • Работа
  • Технологии
  • Все
  • Новости
  • События
  • Статьи
  • Блоги

Resource Governor: управление ресурсами в SQL Server 2008. Часть 1

Resource Governor: управление ресурсами в SQL Server 2008. Часть 1

denish
28.10.2007 17:05

Учат в школе, учат в школе, учат в школе…

 

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

 

Мы делили апельсин,

Много нас, а он один.

Эта долька - для ежа,

Эта долька - для стрижа,

Эта долька - для утят,

Эта долька - для котят,

Эта долька - для бобра,

А для волка - кожура.

Он сердит на нас - беда!!!

Разбегайтесь кто куда!

 

Обратите внимание, что «распил» апельсина происходит по схеме, встречающейся в жизни сплошь и рядом (кстати, исходя из первой фразы, мы вынуждены предположить, что автор является участником дележа и, следовательно, он либо одно из упомянутых животных, либо намеренно себя обделил). Ежик, стриж и бобёр получили по целой дольке, тогда как утята и котята сгруппированы по признаку биологического родства. При этом каждой группе приходится довольствоваться одной долькой на всех, а вот волка совсем обидели, не проявив к нему должной политкорректности – «серому» перепала лишь кожура.

 

Став старше, я сменил слюнявчик на галстук и знаю, что если оставить бухгалтерию «с кожурой» в виде еле трепыхающегося SQL-сервера, да ещё в период сдачи отчётности, то убегать будет некуда. Главбух достанет даже в Гонолулу.

 

Причин, приводящих к таким ситуациям, может быть много. Одна из них – это конкурентная борьба за ресурсы сервера (те самые апельсиновые дольки!) между приложениями и даже отдельными пользователями. Наш малый и, чего греха таить, средний бизнес всё ещё скрепя сердцем идёт на покупку выделенных серверов под каждое приложение. К тому же интуитивно понятно, что ёмкости этих ресурсов порой не хватает именно в считанные дни, тогда как в остальное время сервер превосходно справляется со своей задачей.

 

Что делать, когда менее значимое для компании приложение ведёт себя как саранча, поедая всю доступную серверу память и мешая нормальному функционированию намного более критичных систем? Искать причину в коде? Оптимизировать на коленке? А если это проприетарный продукт, рождённый в муках какой-нибудь софтверной компании, где у программистов руки растут для красоты? Согласитесь, что корректного и быстрого решения здесь нет.

 

Другими словами, в MS SQL Server давно не хватало инструмента, позволяющего регулировать потребление ресурсов и гибко управлять нагрузкой. И такой инструмент появился в Katmai под названием Resource Governor.

Концепция Resource Governor

 

На данный момент в поле зрения RG находятся два типа разделяемых ресурсов – оперативная память и CPU. При этом контроль осуществляется только над ресурсами, которые могут быть выделены процессу MS SQL Server операционной системой. Так, если у вас на той же самой машине установлен, к примеру, IIS, нагружающий процессор на 70%, то, оставшиеся 30% - это максимум, на который может претендовать экземпляр SQL-сервера и максимум, чем может распоряжаться его Resource Governor. Исходя из этих соображений, легко понять, почему RG не умеет регулировать нагрузку на другие компоненты SQL-сервера, такие как Analysis Services, Integration Services или Reporting Services. Все перечисленные компоненты являются отдельными процессами ОС.

 

Коротко рассмотрим основные понятия Resource Governor.

 

Пулы ресурсов (Resource Pools)

 

Пулы позволяют нам разделить ресурсы сервера в соответствии с нашими требованиями по отказоустойчивости и быстродействию приложений.

 

Проведём аналогию с поэтическим зоопарком, описанным ранее.

Допустим, у нас есть апельсин, состоящий из 7 долек, и этот апельсин – ресурс возобновляемый. Мы создали один пул, в котором постановили, что бобёр должен получить не менее 3-х и не более 5 долей апельсина в условиях конкуренции за него. И ещё один пул для ежа, где тому полагается минимум 4 и максимум 6 долек (опять же если на него кто-то ещё претендует). Тем самым, мы задали гарантированный минимум продовольственного обеспечения, который получат бобёр и ёж.

 

Предположим, что пока ёж в командировке, апельсин находится в полном распоряжении бобра. Внимание вопрос: сколько может съесть бобёр? Ответ – Resource Governor позволит ему покушаться на весь апельсин целиком до тех пор, пока из тумана не выйдет ёжик (безраздельное владение бобра ресурсами в отсутствие других потребителей повышает эффективность использования оных).

 

И тут начинается самое интересное. Если ёжик не очень голоден (с утра съел гамбургер) и претендует только на 2 дольки, то бобёр (неделю росинки маковой во рту не было) уже сможет посягнуть только на свой ограниченный паёк в 3-5 долек. А вот если ёж попался жадный и пытается у бобра отобрать его часть фруктового десерта, то Resource Governor не даст в обиду строителя плотин. Бобёр всегда может быть уверен, что при необходимости получит не меньше 3-х долек апельсина.

 

Теперь, когда вы имеете образное представление о пулах, можно обсудить, как они настраиваются в MS SQL Server 2008. Делается это с помощью пары параметров MIN% и MAX% для каждого типа ресурсов (одна пара для CPU, другая – для оперативной памяти). Собственно, мы уже обсудили их назначение. MIN% задаёт гарантированный минимум ресурса, который при необходимости будет предоставлен потребителям пула, а MAX% – верхнюю границу в условиях конкуренции за ресурс.

 

Очевидно, что сумма минимумов всех пулов не должна превышать 100%, в то время как MAX% может быть задан в диапазоне от MIN% до 100%.

 

В MS SQL Server 2008 есть два предопределённых пула – Internal Pool и Default Pool.

 

Internal Pool используется сервером для внутренних нужд. Естественно, что изменять настройки этого пула запрещено. От доступности ресурсов в internal зависит функционирование самого SQL Server, поэтому Resource Governor может позволить ему потеснить «коллег». Даже если такое перераспределение помешает остальным пулам получить свой гарантированный минимум. Для работы с internal предусмотрена одноимённая группа нагрузки (о понятии workload group см. ниже). Разумеется, что другие группы этот пул использовать не могут.

 

В отличие от internal, Default Pool допускает изменение настроек. По своему назначению он похож на любой другой пользовательский пул с тем лишь отличием, что его нельзя удалить. Правда у default есть ещё одно назначение. Когда вы выключаете Resource Governor, настройки пулов сбрасываются (MIN%=0, MAX%=100) и все новые сессии начинают разделять пул Default. Таким образом, конкурентная борьба за ресурсы будет выглядеть приблизительно так, как это происходило в MS SQL Server 2005.

 

Когда речь заходит о пулах, вы можете столкнуться с понятиями Effective MAX% и Shared%.

 

Фактический MAX% (Effective MAX%). Каждый раз, создавая пул с ненулевым значением MIN%, вы тем самым перераспределяете фактически доступный максимум для остальных пулов. Effective MAX% показывает верхний предел ресурсов, доступных пулу в условиях конкуренции и с учётом гарантированных минимумов других пулов. Последнее как раз и отличает Effective MAX% от MAX%.

 

Для вычисления фактического MAX% BOL предлагает использовать формулу

 

Effective Max%x = min(MAX%x, 100 - SUM1..n (MIN%)),

 

где x – интересующий нас пул, а n – общее количество пулов.

 

Согласитесь, не очень наглядно. Поэтому приведённый ниже пример (табличка тоже из BOL) я попытался отобразить графически.

 

Пример. Предположим, мы задали следующую конфигурацию:

 

Pool name

MIN % setting

MAX % setting

Calculated effective MAX %

Calculated shared %

internal

0

100

100

0

default

0

100

25

30

Pool 1

20

100

45

25

Pool 2

50

70

70

20

Pool 3

5

100

30

25

 

Если брать во внимание, что для Internal понятие Effective Max% не применимо (вернее, его значение всегда равно 100%), я продемонстрирую только два самых показательных случая с Pool 1 и Pool 2 (остальные по аналогии).

pools2.gif

На рис.1 показано, в каком процентном соотношении мы распределили ресурс, задав MIN%. Даже если все пулы одновременно (кроме Internal) будут нуждаться в ресурсе, RG сможет гарантировать им установленный минимум. На диаграмме видно, что 25% (заштрихованная область) не закреплено ни за одним пулом, а значит, является разделяемой (shared) частью и может использоваться совместно всеми пулами.

Указывая MAX% = 100% для Pool 1, мы полагаем, что максимальная доля ресурса, доступная пулу, будет колебаться от 20% до 100%. Однако высокая активность потребителей Pool 2 и Pool 3 вынудит сервер отдать им как минимум по 50% и 5% соответственно. Тогда в распоряжении Pool 1 останется 20% минимума и не более чем 25% из разделяемой части. В итоге, фактический MAX% уменьшится со 100% до 45% (20% + 25%).

 

Эта ситуация проиллюстрирована на рис.2. Мы переместили долю Pool 1 (от перестановки соотношение не меняется) на верхний уровень диаграммы и спроецировали на неё MAX%, взяв за основание нижнюю границу Pool 1 MIN%. Область, обведённая красной рамкой, как раз и будет составлять Effective MAX%.

 

Тем же способом рассчитывается фактический максимум для второго пула (рис. 3). Переместив Pool 2 MIN% на вершину распределения, мы отразили на нём MAX%.

Минимальная доля этого пула равна 50%. Как и все остальные пулы, Pool 2 может претендовать на общую часть в 25%, что в сумме даёт 50% + 25% = 75%. Но мы сами ограничили этот показатель, установив MAX% = 70% и, следовательно, Effective MAX% составит 70% (обведено красной рамкой).

 

С фактическим максимумом тесно связано понятие Shared%. Этот показатель используется, чтобы понять, кто из пулов может на время одолжить ресурс и в каком количестве. Вычисляется он по формуле:

 

Shared% x = Effective Max%x - MIN%x

 

 

На наших схемах Shared% - пересечение заштрихованной области с окном, обведённым красной рамкой. Так, к примеру, Pool 2 Shared% = 70% - 50% = 20%.

 

 

Группы нагрузки (Workload Groups)

 

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

 

В контексте Resource Governor группа нагрузки является потребителем ассоциированного с ней пула. Пул может разделяться несколькими группами согласно приоритетам и ограничениям, установленным в этих группах. Такой подход делает ресурсы максимально доступными в критически важные моменты времени.

 

В детском стихотворении, с которого мы начали наше предание о Resource Governor, у бобра есть все признаки группы нагрузки, пусть даже и состоящей из одного представителя. И утята ничем не хуже, они тоже группа нагрузки. И котята. И даже волк-зубами-щёлк, запрашивающий ресурс, подозрительно похож на workload group.

 

На каждый из предопределённых пулов разработчики предусмотрели по группе нагрузки.

 

Internal group является официальным потребителем пула Internal. Мы уже говорили, что Internal Pool оберегается как священная корова, поэтому никакие другие группы не могут на него посягать. Зато такая схема позволяет отслеживать «представительские расходы» самого сервера.

 

Default group создана с целью использования пула Default. Вы можете менять настройки группы, но никогда не заставите её сменить пул. Удалить тоже не получится, как не пытайтесь.

 

Я не буду сейчас вдаваться в подробности поведения внутри групп (например, как утята поделят свою долю апельсина), мы рассмотрим это более детально на последующих примерах.

 

 

Классификация (Classification)

 

Процесс, позволяющий серверу определить, какой запрос к какой группе нагрузки относится, называется классификацией. В качестве объекта классификации в Katmai всегда выступает сессия, а её принадлежность к группе выявляется только на этапе образования. Сменить группу после классификации сессия уже не может (как говорится, бобром родился – бобром умрёшь).

 

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

 

Карл проникся проблемами друзей наших меньших и разработал систему научной классификации (изданную впоследствии как «Systema naturae sive regna tria naturae systematice proposita per classes, ordines, genera, & species»). Натуралист выделил у каждого животного отличительные признаки, позволяющие безошибочно определять его группу. Благодаря усилиям Карла, в лесу вновь восторжествовал закон и порядок.

 

В Resource Governor классификация выглядит приблизительно также. Вы создаёте скалярную пользовательскую функцию (UDF), играющую роль Линнея, и регистрируете её в качестве классификатора. Каждый раз, когда возникает новое подключение, сервер вызывает вашу функцию и ожидает, что она вернёт имя группы для этой сессии. Вы можете реализовать свою логику классификации (вашу собственную «Systema Naturae»), основываясь на так называемых атрибутах соединения (Connection-specific attributes). К ним относятся такие атрибуты сессии как имя пользователя, имя хоста, база данных по умолчанию и т.д.

 

Чтобы отразить процесс классификации, я взял рис.4 из BOL и изменил его до неузнаваемости J.

 

 

rg.gif

 

  1. Пользователь подключается к MS SQL Server 2008.
  2. Resource Governor вызывает функцию-классификатор.
  3. Функция возвращает имя группы согласно имплементированной в ней логике (предположим, это Group 3).
  4. Resource Governor направляет всю последующую нагрузку этой сессии в соответствующую workload group (раз функция вернула Group 3, значит в Group 3).
  5. Группе доступны ресурсы ассоциированного с ней пула (для Group3 это Pool 1).

 

Ещё раз подчеркну важный момент. Если при создании сессия была направлена в Group 3, то перебросить потом её нагрузку, например, в Group 2 или Group 1 уже не представляется возможным.

 

Также следует внимательно относиться к «внутренностям» функции-классификатора и тщательно её тестировать перед вводом в эксплуатацию. Неправильная работа этой UDF может привести к невозможности пользователей подключиться к серверу или к длительному ожиданию подключения.

 

Правда, некоторые последствия некорректной реализации classifier UDF сервер может устранить сам. Продемонстрируем это на примере с лесными обитателями (я уже чувствую, как во мне просыпается Николай Дроздов).

 

Итак, лесная опушка. Солнце светит, бобёр строит плотину, ничто не предвещает беды. И тут с высоких гор спускается Йети и просит выделить ему долю апельсина. Звери в шоке, Линней хватается за сердце, на поляне возникает паника. Где-то вдалеке раздаются автоматные трели и недовольные выкрики «понаехали тут!».

 

Никто не знает что делать. С одной стороны, в «Systema Naturae» о Йети не сказано ни слова. С другой – снежный человек существует и стоит во всей красе прямо перед ними, хоть сейчас бери и портрет пиши.

 

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

 

А лесные жители тем временем договорились не вспоминать о неприятном инциденте, и вскоре на опушке снова восторжествовал закон и порядок.

 

К счастью, Resource Governor не может себе позволить ссорится с пользователями. Если функция-классификатор не даёт однозначного ответа о принадлежности сессии к группе (возвращает null или название несуществующей группы), то нагрузка этой сессии будет перенесена на плечи Default group, а ресурсы будут черпаться из пула Default.

 

Продолжение следует...

denish
28.10.2007 17:05
Комментариев:3 RSS Просмотров:242
Теги: SQL
mihailik
28.10.2007 20:00
Вот это супер статья!

Такие уж у меня попсовые вкусы, но именно такой стиль объяснения со ссылками а аналогиями мне кажется лучшим в мире.

Хотя всё-таки не совсем понятно кто же определяет принадлежность к Internal group. Если это функцией "вручную" определяется, то так ведь все гарантии для системных процессов оказываются под вопросом. Впрочем, наверное, это как раз попадает в "продолжение следует".

Спасибо, пиши в лёгком стиле ещё, пожалуйста.
Ссылка
Nikolay Denishchenko
28.10.2007 20:20
2 mihailik
Кого отправлять в internal решает сам сервер и мы не можем на этот процесс повлиять. Даже если мы напишем такой пьяный классификатор, который будет во всех сессиях узнавать internal, RG проигнорирует эти указания, перенаправив нагрузку в default. Единственный способ, позволяющий вашей сессии работать в контексте Internal group -- подключиться в Dedicated Admin Connection (DAC). Тогда все запросы в DAC-сессии будут потреблять ресурсы пула Internal. И с этим надо быть очень осторожным.

В последующих частях я чуть подробнее расскажу об Internal и его влиянии на другие группы.
Ссылка
Evgeny Fedyakov
14.12.2007 7:45
Классно, прочитал на одном дыхании.
Ссылка

Nikolay Denishchenko

denish разработчик
(none)
  • Блог

Облако тегов

events programming security sql system development
Строишь сложные системы? Хостинг от Parking.Ru

Записи

Популярные
  • mezastel > Сокращенный генератор C# в стиле Zen Coding
  • Enrey > О поедании памяти DataTable
  • XaocCPS > Установка Visual Studio 2010 RC
  • serbelyakov > DataGridView
  • Sergey Grigorev > Pex как инструмент для автоматизиции тестирования в .NET
  • XaocCPS > Bundler : клиентская оптимизация JavaScript в ASP.NET
  • shapovalov > AtomicCms - новая система управления сайтом на база ASP.NET MVC
  • mbakirov > Must have плагины для Visual Studio 2010 RC
  • paxer > Kentico CMS как платформа для разработки веб приложений на ASP.NET
  • clevelus > Новая электронная книга о Visual Studio 2010
Все популярные записи
Обсуждаемые
  • Enrey > О поедании памяти DataTable
  • sos > Работа на двух экранах - повышение производительно­сти или рассредоточение внимания?
  • paxer > Kentico CMS как платформа для разработки веб приложений на ASP.NET
  • serbelyakov > DataGridView
  • shapovalov > AtomicCms - новая система управления сайтом на база ASP.NET MVC
  • SergeyT. > Что нового в третьем издании книги Джеффри Рихтера "CLR via C#"
  • spugachev > Создание внебраузерных Silverlight приложений. Часть 1.
  • XaocCPS > Bundler : клиентская оптимизация JavaScript в ASP.NET
  • RaveNoX > Экспорт функции из .Net dll или пишем managed функцию для rundll32
  • ~44-ый > Немного о юзабилити. Веб-сайты.
Все обсуждаемые записи

Блоги

Новые
  • desco> Случайные записи
  • sashaeve> Блог Microsoft .NET User Group Винница
  • lukesky> Новости технологии NitrosBase
  • RaveNoX> Arthur Kraev
  • Rockie> Gennady G.(Rockie)
  • Новатор> SharePoint. Шаг за шагом.
  • ivanoff> Denis Ivanov
  • paxer> Программировани­е - как страсть
  • Realist> Build Your Web
  • veleslav> veleslav
Обсуждаемые
  • mihailik> Олег Михайлик
  • ceo> Нотатник Вiктора Шатохiна [MSFT]
  • gaidar> Gaidar Magdanurov
  • MikhailChernomo­rdikov> Mikhail Chernomordikov [MSFT]
  • Alexander Lozhechkin [MSFT]> Alexander Lozhechkin
  • agladkik> Andrey Gladkikh: Microsoft Dynamics
  • beerbong> Bong Blog
  • sos> Dmitry Soshnikov [MSFT]
  • not-a-kernel-gu­y> Зеркало: Not a kernel guy
  • sergun> Sergey Zwezdin
О сайте   Свяжитесь с нами   Конфиденциальность   Версия для печати
Работает на 1С-Битрикс: Управление сайтом ASP.NET  |  Хостинг на Parking.Ru