Дата публикации: 13 августа 2013г.

Автор: Боб Дорр – главный эскалационный инженер поддержки SQL Server
По материалам статьи: How It Works: SQL Server 2012 Database Engine Task Scheduling

В течении последних лет в разных источниках были описаны алгоритмы работы планировщика SQL Server. В частности, в статье «The Guru’s Guide to SQL Server Architecture and Internals» есть глава, написанная разработчиком планировщика (Sameer) и Кеном Хендерсеном. Автор этой статьи иранее описывал некоторые технические детали алгоритмов планирования задач SQLServer.

Эта статья посвящена некоторым изменениям, которые появились в SQL Server 2012. Статья не претендует на охват всех нюансов (коих слишком много), вместо этого будет частично проиллюстрирована работа алгоритма в его современной реализации, что позволит вам лучше понимать поведение планировщика SQLServer . Автор допускает по тексту несколько вольную трактовку в описании алгоритмов, преследуя цель избавить статью от лишней официальности.

Алгоритм Recap

Планирование задания начинается с уровня NUMA узла. Базовая ветвь алгоритма представляет собой простой последовательный перебор ( roundrobin ) узлов, который определяет выбор места назначения новых подключений. Следуя этому алгоритму, каждое последующее подключение будет назначаться планировщику того же NUMA узлу.

Примечание: в SQLServerBooksOnlineописано, как осуществить привязку задания к указанному NUMA узлу.

Новое соединение отдаётся менее нагруженному планировщику, который принадлежит этому же узлу NUMA. Загруженность определяется расчётным коэффициентом ( loadfactor ), смысл которого довольно близко определяет число задач, которыми занимается планировщик. Подробные сведения о планировщике можно найти в DMV ( sys . dm _ os _ schedulers ). Выбранный планировщик становится предпочтительным (принято называть такой выбор подсказкой планировщика « schedulerhint ») на протяжении всей жизни соединения.

Задача остаётся привязанной к планировщику до тех пор, пока клиент не пошлёт на сервер новую команду (пакет T -SQL т.е. « batch », RPC и т.п.). В SQL Server устроено так что, если задача назначена планировщику, она будет привязана к нему на протяжении исполнения только текущей команды (до завершения пакетной обработки).

Привязка задачи зависит и от коэффициента загрузки. Если предпочтительный планировщик (в момент подключения) загружен на 20% больше, чем другие планировщики этого же NUMA узла, задача назначается планировщику текущего узла, у которого окажется самая маленькая загрузка. Часто это называют правилом 120%. После того, как загрузка предпочтительного планировщика достигает 120% по отношению к загрузке других планировщиков текущего NUMA узла, новые задачи будут привязаны к другим планировщики этого же узла.

Изменения в SQL Server 2012 касаются только корпоративной редакции сервера (EE SKU)

Поведение SQL Server 2012 из «коробки» не претерпело каких – либо изменений. Так что же побудило автора написать эту статью? Дело в том, что все другие редакции, которые не Enterprise Edition, используют ту же самую фундаментальную логику, которая была внедрена ещё в SQL Server 7.0 (UMS планирование), как это было описано выше. В редакцию EESCU были внесены некоторые улучшения, направленные на развитие возможностей управления ресурсами процессора. Обратите внимание, что только в том случае, когда используется редакция SQLServerEnterpriseEdition, появляется возможность задействовать те новшества, о который пойдёт речь ниже, в этой статье.

Изменения в привязке подключений: Используем для демонстрации алгоритма рисунок ниже. Привязка выполняется по кругу, по порядку узлов. Вначале к узлу 1, потом к узлу 2, потом к узлу 1 и так далее. Основные алгоритмы привязки подключений одинаковы для всех редакций SQL Server 2012. Как показано на рисунке, порт 1433 назначен обоими NUMA узлами поэтому подключения циклически будут направляться обоим узлам. Запрашивается величина текущей загрузки планировщиков, принадлежащих выбранному узлу, и новое подключение назначается планировщику с наименьшей загрузкой . Этот планировщик становится предпочтительным планировщиком на протяжении всего срока жизни подключения.

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

Рисунок 1. Привязка после подключения к предпочтительному планировщику с наименьшей загрузкой

Версии до SQL Server 2012 в любых редакциях или SQL Server 2012 не в редакции Enterprise Edition

Запрос новой задачи (новый пакет, RPC или при пере-подключении…) будет использовать привязку к своему предпочтительному планировщику. В нашем примере предпочтительным является планировщик №2. Текущий выбор планировщика ( schedulerhint ), указывающий на предпочтительный планировщик, будет зависеть от того, превышает ли коэффициент загрузки 120%, по сравнению с другими планировщиками того же самого узла, и, если это так, то задача будет привязана к другому планировщику. При этом, для подключения предпочтительный планировщик не изменяется.

На показанном ниже рисунке приводится пример выбора планировщика для нового пакета инструкций ( newbatch ). Предпочтительным планировщиков в данном случае является планировщик №2, но его коэффициент загрузки уже вырос до 13-ти, что превышает 120% от планировщика №1, у которого коэффициент загрузки равен 10-ти. Таким образом, пакет будет назначен планировщику №1, поскольку считается, что он менее загружен и, вероятно, обеспечит больше процессорных ресурсов для задачи.

Рисунок 2.

Версия в редакции SQL Server 2012 Enterprise Edition

Начиная с SQL Server 2012 EnterpriseEdition поведение движка при выборе планировщика для новой задачи (новый пакет, RPC или после отключения…) изменилось, это происходит теперь только после того, как соединение было установлено и ему был назначен ресурсный пул (пока нет соединения, нет указания на предпочтительный планировщик!).

Примечание:Если регулятор ресурсов не настроен, будет использоваться системный пул ресурсов DEFAULT.

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

Каждый планировщик получает указание пула процессорных ресурсов, далее мы будем называть эту структуру «Указание пула» (LF RG Pool). Это указание учитывается одновременно с учётом традиционного коэффициента загрузки. Для привязки задач к планировщикам, вместо основанного на количестве задач коэффициента загрузки, используется коэффициент загрузки, привязанный к указанию пула. Фактически, SQL Server отслеживает среднее число указаний пула по каждому из узлов.

Рисунок 3.

Для привязки задачи к планировщику вначале предлагается «предпочтительный» планировщик (его подключению сообщает структура «подсказка планировщика»). Этот планировщик будет предлагаться до тех пор, пока, после добавления ему очередной задачи, величина его загрузки не станет такой, что потенциальные возможности использования им ресурсов станут меньше 80% от среднего по планировщикам пула, находящихся в одном с предпочтительным планировщиком NUMA узле.

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

Давайте рассмотрим пример на более детальном уровне, который арифметически покажет, как это всё действует.

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

В этом примере новые задачи будут привязаны к планировщику №2, у которого для текущего пула доступно больше ресурсов, в данный момент на задачу приходится в 6,25 раз больше ресурсов, чем минимально возможно. В то же время, у планировщика №1 ресурсов больше минимального только в 5 раз

Планировщик

Число возможных задач для пула регулятора ресурсов

Число запущенных задач пула

Средняя величина ресурсов на задачу

1

50

10

5

2

50

8

6,25

Сейчас это лучший выбор – больше ресурсов для обеспечения задач в этом пуле

Текущее среднее: 5.625 = (6.25 + 5)/ 2

Теперь предположим, у нас появилось новое задание для привязки, а предпочтительным является планировщик №1. SQL Server 2012 EnterpriseEdition использует текущее среднее и наибольшее потребление ресурсов, чтобы вычислить, к какому планировщику следует привязать задачу.

Отсечка восьмидесяти процентов = 4.5008 (средняя ресурсная величина задач в рамках одного пула рассчитывается для всех планировщиков одного узла ).

Планировщик

Число возможных задач для пула регулятора ресурсов

Число запущенных задач пула +1 дополнительная

Средняя величина ресурсов на задачу

1

50

11

4,5454

Не ниже 80-ти процентов

2

50

9

5,55

Добавление ещё одной задачи в тот же пул на планировщике №1 не опускает среднее число задач ниже 80-й процентов для всего NUMA узла. Привязка этого запроса будет выполнена к планировщику №1.


Скорректированное текущее среднее: 5,3977 (6,25 + 4,5454) / 2 и отсечка 80-ти процентов = 4,3181

Теперь давайте ещё раз пытаемся добавить задачу на планировщике №1. На этот раз в случае привязки задачи к планировщику №1 среднее опустится ниже 80-й процентов. Поэтому SQL Server взамен первому планировщику найдет в пуле планировщик с наибольшим количеством ресурсов и назначит задачу ему. В нашем примере это будет планировщик №2.

Планировщик

Число возможных задач для пула регулятора ресурсов

Число запущенных задач пула +1 дополнительная

Среднее по пулу число задач +1

1

50

12

4,1666

Ниже 80-й процентов

2

50

9

5,55

Последнее изменение приведёт к следующему распределению нагрузки:

Планировщик

Число возможных задач для пула регулятора ресурсов

Число запущенных задач пула +1 дополнительная

Среднее по пулу число задач +1

1

50

11

4,5454

2

50

9

5,55

 Добавлена задача

Скорректированное текущее среднее: 5,047 (5,55 + 4,5454) / 2

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

Флаги трассировки следует использовать с большой осторожностью!

Можно упомянуть недокументированные флаги трассировки, которые авторуникогда не доводилось видеть используемыми в промышленных системах. Для управления привязкой к планировщикам существует несколько таких флагов. Разумеется, эти флаги не предназначены для постоянного использования и их лучше использовать только после консультаций с поддержкой Microsoft SQL Server. Поскольку флаги влияют на алгоритмы привязки задачи они могут повлиять на параллелизм и производительность системы.

-T8008 – заставляет игнорировать подсказку планировщика. Привязка будет сделана к планировщику с наименьшей нагрузкой (на основе пулов в SQL 2012 Enterprise Edition или коэффициента нагрузки для предыдущих версий и младших редакций).

-T8016 – заставляет игнорировать балансировку нагрузки. Всегда выбирается предпочтительный планировщик.