Относится к: Современные знания о SQL Server и Hyperthreading
Недавно мы обновили наш сервер базы данных Windows 2008 R2 с X5470 к X5560. Теоретически оба процессора имеют очень схожую производительность, во всяком случае, X5560 немного быстрее.
Однако производительность SQL Server 2008 R2 в последние дни была довольно низкой, а загрузка ЦП была довольно высокой.
Ожидаемая продолжительность жизни страницы огромна, мы получаем почти 100% попадание в кэш для страниц, поэтому память не является проблемой.
Когда я бежал:
SELECT * FROM sys.dm_os_wait_stats
order by signal_wait_time_ms desc
Я получил:
wait_type waiting_tasks_count wait_time_ms max_wait_time_ms signal_wait_time_ms ------------------------------------------------------------ -------------------- -------------------- -------------------- -------------------- XE_TIMER_EVENT 115166 2799125790 30165 2799125065 REQUEST_FOR_DEADLOCK_SEARCH 559393 2799053973 5180 2799053973 SOS_SCHEDULER_YIELD 152289883 189948844 960 189756877 CXPACKET 234638389 2383701040 141334 118796827 SLEEP_TASK 170743505 1525669557 1406 76485386 LATCH_EX 97301008 810738519 1107 55093884 LOGMGR_QUEUE 16525384 2798527632 20751319 4083713 WRITELOG 16850119 18328365 1193 2367880 PAGELATCH_EX 13254618 8524515 11263 1670113 ASYNC_NETWORK_IO 23954146 6981220 7110 1475699 (10 row(s) affected)
Я также побежал
-- Isolate top waits for server instance since last restart or statistics clear
WITH Waits AS (
SELECT
wait_type,
wait_time_ms / 1000. AS [wait_time_s],
100. * wait_time_ms / SUM(wait_time_ms) OVER() AS [pct],
ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS [rn]
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE',
'SLEEP_TASK','SLEEP_SYSTEMTASK','SQLTRACE_BUFFER_FLUSH','WAITFOR','LOGMGR_QUEUE',
'CHECKPOINT_QUEUE','REQUEST_FOR_DEADLOCK_SEARCH','XE_TIMER_EVENT','BROKER_TO_FLUSH',
'BROKER_TASK_STOP','CLR_MANUAL_EVENT','CLR_AUTO_EVENT','DISPATCHER_QUEUE_SEMAPHORE',
'FT_IFTS_SCHEDULER_IDLE_WAIT','XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN'))
SELECT W1.wait_type,
CAST(W1.wait_time_s AS DECIMAL(12, 2)) AS wait_time_s,
CAST(W1.pct AS DECIMAL(12, 2)) AS pct,
CAST(SUM(W2.pct) AS DECIMAL(12, 2)) AS running_pct
FROM Waits AS W1
INNER JOIN Waits AS W2 ON W2.rn <= W1.rn
GROUP BY W1.rn, W1.wait_type, W1.wait_time_s, W1.pct
HAVING SUM(W2.pct) - W1.pct < 95; -- percentage threshold
И получил
wait_type wait_time_s pct running_pct CXPACKET 554821.66 65.82 65.82 LATCH_EX 184123.16 21.84 87.66 SOS_SCHEDULER_YIELD 37541.17 4.45 92.11 PAGEIOLATCH_SH 19018.53 2.26 94.37 FT_IFTSHC_MUTEX 14306.05 1.70 96.07
Это показывает огромное количество запросов синхронизации времени, включающих параллелизм (высокий CXPACKET). Кроме того, как ни странно, многие из этих проблемных запросов выполняются на нескольких ядрах (у нас нет подсказок MAXDOP нигде в нашем коде)
Сервер не находился под нагрузкой более суток. Мы сталкиваемся с большой разницей в выполнении запросов, обычно многие запросы кажутся медленнее, чем на нашем предыдущем сервере БД, а ЦП действительно высок.
Поможет ли отключение Hyperthreading сократить использование ЦП и увеличить пропускную способность?
Я согласен, что
Похоже, нам нужно настроить две вещи:
MAXDOP (максимальные степени параллелизма). Все, что я читал, указывает на то, что иметь неограниченное количество возможностей - плохая идея, и Документация Microsoft говорит:
Установка этого параметра [MAXDOP] на большее значение [, чем 8] часто вызывает нежелательное потребление ресурсов и снижение производительности.
что-нибудь выше, чем 8
обычно не рекомендуется .. поэтому я установил его на 4
на данный момент. Первоначально он был нулевым (неограниченным).
Порог стоимости параллелизма. По-видимому, по умолчанию 5
здесь считается довольно низким значением по умолчанию в соответствии с несколькими сообщениями SQL MVP, которые я нашел - мы можем настроить это чтобы уменьшить количество попыток параллелизма даже в планировщике.
Но, честно говоря, они кажутся обходными путями; Я думаю, что истинное решение для нашей рабочей нагрузки (тяжелый полнотекстовый индекс) - отключить HT.
Я все еще чувствую это тестирование вашей конкретной рабочей нагрузки, согласно первоначальному ответу, это единственный способ убедиться. Это не идеальный ответ, когда вы пытаетесь настроить производственную систему (поэтому я бы спросил, можно ли получить идентичный испытательный стенд в системах, где и производительность, и доступность действительно имеют значение), но это единственный, который мне действительно удобен с участием.
Мы можем говорить о теории о том, должна ли Hyperthreading повредить или улучшить ситуацию в целом (я считаю, что это скорее повредит, чем поможет на серверах, поэтому для «общего» развертывания я бы, вероятно, отключил его), но есть есть только один способ убедиться, что это будет иметь значение в вашем конкретном случае, и это попробовать и убедиться.
Anandtech обнаружил, что при чистой нагрузке чтения это немного повредило, а при большой нагрузке записи это было немного лучше. Я не видел ничего, что заставляло бы меня думать, что это принесет вам успех намного хуже, чем -5%, или выигрыш, намного превышающий 15%. Обратите внимание, что для Atom это огромная победа, но это очень странный процессор.
Все, что вы изменили, это процессор? Вы перешли от кеш-памяти 12 МБ и 4 потоков, то есть 3 МБ кеш-памяти на поток, к 8 МБ кеш-памяти и 8 потоков, то есть 1 МБ на поток. Это слишком упрощает, но я уверен, что это то, что вас убивает, вы раньше запускали запросы в кеше, а теперь запускаете их из ОЗУ, потому что им нужно более 1 МБ, но менее 3 МБ. Отключение HT, вероятно, поможет, но я бы вернулся к старому процессору. Отключите HT, и вы получите 2 МБ на поток, но если ваша рабочая нагрузка так сильно падает, это не поможет. Вполне возможно, что старый процессор с кеш-памятью 12 МБ намного быстрее справится с вашей рабочей нагрузкой.
Я бы попробовал выключить HT и посмотреть, является ли это улучшением, но я подозреваю, что кеш - это король вашей рабочей нагрузки, и вам, возможно, придется вернуться к чипу 12 МБ.
Гиперпоточность - это, в лучшем случае, просто способ абстрагироваться от переключения задач от операционной системы и размещения ее на кристалле с прямым доступом к кешам L1 и L2, что ускоряет переключение задач.
Тестирование с помощью VMWare показало, что отключение HT не имело заметной разницы при стандартной нагрузке и на 5% больше при большой нагрузке из-за того, что ESXi достаточно умен, чтобы знать разницу между «настоящим» потоком и «поддельным» потоком. (есть много более того, но это с точки зрения непрофессионала). SQL Server 2005 не так уж и умен, но в сочетании с современной операционной системой не должно быть особых преимуществ в отключении HT.
Все это говорит о том, что я согласен с Рональдом, что, скорее всего, это будет ваш кеш L2. Уменьшение размера кэша на 33% является значительным, и когда мы определяем наши серверы SQL, мы всегда каждый раз используем кеш с превышением тактовой частоты.
Исходя из моего опыта, HT заставлял операции ввода-вывода постоянно выполнять операции ввода-вывода на моем из моих активных узлов в кластере Windows 2008 R2 (под управлением SQL Server 2008 R2). Интересным фактом было то, что это не было отражено ни в статистике ожидания, ни в pssdiag, который я запускал для поддержки Microsoft.
Я заметил низкий уровень ввода-вывода, просто наблюдая за счетчиками ОС для физического диска. Как указал Сэм, я написал об этом Вот и Вот
Если вы НЕ испытываете проблем с вводом-выводом и ограничены процессором, я предлагаю вам начать с этого:
Определите, какие процессы и блоки T-SQL вызывают наибольшую загрузку ЦП. По нашему опыту, после того, как мы устранили проблему с вводом-выводом (отключив HT), мы определили код, который ужасно работал в 2008 R2 и отлично работал в 2005 году. Я писал об этом Вот.
При высокой нагрузке запустите процедуру sp_whoisactive Адама Мачаника. Вы можете скачать его с Вот. У нас была очень высокая загрузка ЦП из-за чрезмерного количества логических операций чтения (20 миллионов на запрос) из-за действительно плохого плана. Наши процессы выполняли анти-полусоединения с таблицами, которые были секционированы.
Моя следующая рекомендация - запустить профилировщик, чтобы идентифицировать набор кода T-SQL, который требует одновременного логического чтения ЦП и ввода-вывода.
С помощью описанных выше шагов мы смогли настроить процессы, вызывающие нарушение, и перейти от устойчивого использования ЦП с 85% до почти нулевого.
Удачи и, пожалуйста, напишите мне, если найдете исправление, поскольку я хотел бы добавить этот случай в свой блог.
Спасибо
Оскар
Трудно определить, хороша ли HT или плоха.
Это действительно зависит от модели загрузки сервера, основанной на опыте и чтении. То есть, когда это влияет на производительность, это происходит плохо: иначе вы этого не заметите.
Теория, которую я прочитал, заключалась в том, что потоки совместно используют кеш, что означает, что в неблагоприятных условиях каждый поток может перезаписать кеш другого потока. Если у вас не так много параллелизма или у вас много коротких запросов, это может не повлиять на вас.
Я пробовал использовать MAXDOP и привязку к процессору (еще в моей последней реальной роли администратора базы данных на SQL Server 2000), но так и не смог найти ничего убедительного: но только для моего магазина в то время.
В качестве быстрого теста вы можете настроить привязку процессора для использования только физических ядер (меньшие числа) и посмотреть, что произойдет.
Однако в лучшем случае вы теряете половину своих ядер. В настоящее время это может не иметь значения по сравнению с тем, с чем я играл несколько лет назад, когда было 2 против 4 или 4 против 8. Теперь это 8 против 16 или 16 против 32.
Редактировать: Тест Славы Окс
К сожалению, я не думаю, что вы получите более окончательный ответ, чем «попробуйте отключить гиперпоточность и посмотрите, поможет ли это».
Несмотря на полезный ответ Джонатана в моей исходной беседе (на которую вы ссылались в своем вопросе), мне так и не удалось получить каких-либо окончательных доказательств влияния HT на конкретные серверы, которые я исследовал. В моем случае серверы уже были запланированы для замены, поэтому мы просто позволили этим заменам, так сказать, «позаботиться о проблеме».
Мой совет:
Попробуйте установить MAX Degree of Parallelism на уровне сервера равным 1. Параллелизм в SQL - это большинство в любом случае полезен для более крупных и длительных запросов, и ваша нагрузка (я предполагаю) в любом случае состоит из огромного количества небольших запросов. Это должно полностью исключить ожидания CXPACKET. Это может сделать некоторые отдельные запросы немного дольше, но должно обеспечить большую «пропускную способность» общих запросов на сервере.
У меня были хорошие результаты на серверах OLTP. Другие типы серверов (серверы отчетов, серверы обработки, хранилища данных) определенно нуждаются в установке MAXDOP выше.
И, чтобы быть ясным, этот параметр все равно позволит SQL использовать несколько потоков для каждой отдельной таблицы в JOIN, поэтому вы на самом деле не устраняете параллелизм полностью.
По крайней мере, стоит попробовать, поскольку это изменение настройки вступает в силу немедленно и даже не требует перезапуска службы SQL: http://msdn.microsoft.com/en-us/library/ms181007.aspx
Это означает, что вы можете немедленно переключить его обратно, если все пойдет к черту.
Отключение гиперпоточности в BIOS потребует полной перезагрузки сервера, поэтому это немного более рискованно.
К слову, у нас также неожиданно низкая производительность после обновления сервера. Оказалось, это из-за проблем с BIOS и энергосбережением процессора. По умолчанию сервер (HP) игнорирует управление скоростью ЦП ОС и использует собственный алгоритм. Изменение этого параметра на управление ОС и обновление BIOS привело к значительным улучшениям. Были некоторые примечания к выпуску (не могу их сейчас найти), что была ошибка BIOS, которая блокировала процессор на самом низком уровне производительности.