2010-06-10 2 views
2

Я использую SQL Server 2008 для Windows Server 2008 R2, все sp'd up.Ошибка блокировки SQL/зависания

Я получаю случайные проблемы с тем, что SQL Server висит с использованием ЦП на 100% на нашем реальном сервере. Кажется, все время ожидания SQL Sever, когда это происходит, предоставляется SOS_SCHEDULER_YIELD.

Здесь хранится Proc, который вызывает зависание. Я добавил «WITH (NOLOCK)», пытаясь исправить то, что кажется проблемой блокировки.

ALTER PROCEDURE [dbo].[MostPopularRead] 
AS 
BEGIN 
SET NOCOUNT ON; 

SELECT 
    c.ForeignId , ct.ContentSource as ContentSource 
    , sum(ch.HitCount * hw.Weight) as Popularity 
    , (sum(ch.HitCount * hw.Weight) * 100)/@Total as Percent 
    , @Total as TotalHits 
from 
    ContentHit ch WITH (NOLOCK) 
    join [Content] c WITH (NOLOCK) on ch.ContentId = c.ContentId 
    join HitWeight hw WITH (NOLOCK) on ch.HitWeightId = hw.HitWeightId 
    join ContentType ct WITH (NOLOCK) on c.ContentTypeId = ct.ContentTypeId 
where 
    ch.CreatedDate between @Then and @Now 
group by 
    c.ForeignId , ct.ContentSource 
order by 
    sum(ch.HitCount * hw.HitWeightMultiplier) desc 
END 

Хранимая процедура считывает данные из таблицы «ContentHit», которая представляет собой таблицу, которая отслеживает, когда содержимое на сайте щелчке (он получает удар довольно часто - что-нибудь от 4 до 20 ударов в минуту). Поэтому довольно ясно, что эта таблица является источником проблемы. Существует хранимый proc, который вызывается для добавления дорожек с удалением в таблицу ContentHit, его довольно тривиально, он просто создает строку из переданных параметров, которая включает в себя несколько выборок из некоторых таблиц поиска, а затем основную вставку:

BEGIN TRAN 
insert into [ContentHit] 
    (ContentId, HitCount, HitWeightId, ContentHitComment) 
values 
    (@ContentId, isnull(@HitCount,1), isnull(@HitWeightId,1), @ContentHitComment) 
COMMIT TRAN 

Таблица ContentHit имеет кластерный индекс в столбце ID, и я добавил еще один индекс в CreateDate, поскольку он используется в select.

Когда я рассматриваю проблему, я вижу, что хранимая процедура выполняется ровно 30 секунд, тогда возникает исключение таймаута SQL. Если это имеет значение, веб-приложение использует его ASP.NET, и я использую Subsonic (3) для выполнения этих хранимых процедур.

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

РЕДАКТИРОВАТЬ: MostPopularRead, хранящийся в proc, называется очень редко - его вызывают на домашней странице сайта, но результаты кэшируются в течение дня. Модель событий, которые я вижу, - это когда я очищаю кеш, на домашний сайт поступают несколько запросов, и все они попадают в сохраненный процесс, потому что он еще не кэширован. SQL Server затем максимизируется и может быть разрешен только путем перезапуска процесса sql-сервера. Когда я это сделаю, обычно proc выполнит ОК (примерно через 200 мс) и вернет данные в кеш.

EDIT 2: Я проверил план выполнения, и запрос выглядит довольно здорово. Как я сказал ранее, когда он запускается, требуется всего 200 мс для выполнения. Я добавил MAXDOP 1 в оператор select, чтобы заставить его использовать только одно ядро ​​ЦП, но я все еще вижу проблему. Когда я смотрю на время ожидания, я вижу, что XE_DISPATCHER_WAIT, ONDEMAND_TASK_QUEUE, BROKER_TRANSMITTER, KSOURCE_WAKEUP и BROKER_EVENTHANDLER занимают огромное количество времени ожидания.

EDIT 3: Ранее я думал, что это было связано с Subsonic, нашим ORM, но, переключившись на ADO.NET, erros все еще жив.

+0

Звучит довольно странно, вы проверили с профилировщиком, что делает Subsonic? Вызывается ли SP так же, как и вручную? – VladV

+0

Попробуйте перетащить данные из содержимого, попавшего в таблицу temp, а затем сделайте полный запрос о присоединении к другим таблицам. – Paul

ответ

2

Remove the NOLOCK hint.

Откройте запрос в SSMS, запустите SET STATISTICSIO ON и запустите запрос в процедуре. Позвольте ему закончить и опубликовать здесь сообщения статистики IO. Затем опубликуйте определения таблиц и все индексы, определенные на них. Тогда кто-то сможет ответить с необходимыми индексами.

Как и во всех проблемах с производительностью SQL, текст запроса в значительной степени не имеет значения без полного определения схемы.

индекс покрытия

догадка будет:

create index ContentHitCreatedDate 
    on ContentHit (CreatedDate) 
    include (HitCount, ContentId, HitWeightId); 

Update

XE_DISPATCHER_WAIT, ONDEMAND_TASK_QUEUE, BROKER_TRANSMITTER, KSOURCE_WAKEUP и BROKER_EVENTHANDLER: вы можете спокойно игнорировать все эти ожидания.Они отображаются, потому что они представляют собой потоки, припаркованные и ожидающие отправки XEvents, Service Broker или внутренних элементов потока пула SQL. Поскольку они проводят большую часть своего времени, припаркованные и ожидающие, они получают объяснение нереалистичным временем ожидания. Игнорируй их.

+0

Спасибо Ремусу. Но, как я сказал ранее, когда я запускаю запрос, он работает очень эффективно (200 мс), если он не зависает, поэтому я не ожидал, что другой указатель решит эту проблему. Добавленный вами индекс - тот, который я добавил в эту таблицу. Я отправлю эту информацию, если мои тесты Subsonic ORM ничего не раскрывают. –

0

Если вы считаете, ContentHit быть источником вашей проблемы, вы можете добавить Covering Index

CREATE INDEX IX_CONTENTHIT_CONTENTID_HITWEIGHTID_HITCOUNT 
    ON dbo.ContentHit (ContentID, HitWeightID, HitCount) 

Посмотри на Query Plan, если вы хотите быть уверены в узком месте в вашем запросе.

2

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

Как часто называется [MostPopularRead] SP и сколько времени требуется на выполнение? Агрегация в вашем запросе может быть достаточно интенсивной, особенно если есть много данных и/или неэффективных индексов. Таким образом, вы можете столкнуться с высоким давлением процессора - в основном, спрос на процессорное время слишком высок.

Я бы рассмотреть следующее:

  1. Проверьте, что другие запросы выполняются в то время как процессор 100% занят? Посмотрите на sys.dm_os_waiting_tasks, sys.dm_os_tasks, sys.dm_exec_requests.

  2. Посмотрите на план запроса [MostPopularRead], попробуйте оптимизировать запрос. Довольно часто неэффективный запрос является основной причиной проблемы производительности, а оптимизация запросов намного проще, чем другие методы повышения производительности.

  3. Если план запроса параллелен, и запрос часто вызывается несколькими клиентами одновременно, форсирование однопоточного плана с подсказкой MAXDOP = 1 может помочь (обильное использование параллельных планов обычно указывается SOS_SCHEDULER_YIELD и CXPACKET) ,

Кроме того, взгляните на эту статью: Performance tuning with wait statistics. Это дает довольно хорошее резюме различных типов ожидания и их влияния на производительность.

P.S. Легче использовать УРОВЕНЬ ИЗОЛЯЦИИ SET TRANSACTION READ UNCOMMITTED перед запросом вместо добавления (nolock) к каждой таблице.

+0

Я согласен с этим ответом. Попробуйте настроить максимальную степень параллелизма. Как ни странно, я видел ситуации, когда * снижение * max dop может улучшить производительность. –

+0

Хорошо спасибо. Я начну изучать MAXDOP и узнаю больше о том, что происходит, когда процессор находится на 100%. –

+0

MostPopularRead кэшируется после вызова, поэтому его не следует вызывать часто. Однако из-за этой проблемы, пока сайт ожидает выполнения MostPopularRead, поэтому он может быть кэширован, загружает больше запросов и запускает сохраненный процесс, который возникает, когда SQL Server зависает. Если я запустил хранимую процедуру вручную из студии управления, она не занимает больше 0,5 с, обычно около 200 мс. –

0

По умолчанию в sql-сервере используются все ядра/процессоры для всех запросов (макс. Параметр DoP> расширенное свойство, DoP = степень параллелизма), что может привести к 100% -ному процессору, даже если только одно ядро ​​на самом деле ждет некоторых I/O.
Если вы ищете сеть или этот сайт, вы найдете ресурс, объясняющий это лучше меня (например, мониторинг ваших операций ввода-вывода, несмотря на то, что вы видите проблему с привязкой к ЦП).
На одном сервере мы не могли изменить приложение с плохим запросом, который заблокировал все ресурсы (ЦП), но, установив DoP на половину количества ядер, нам удалось избежать «остановки» сервера. Влияние на запросы, которые были менее параллельными, в нашем случае было незначительным.

-
Дом

0

Спасибо всем, кто опубликовал, я получил отличные советы по настройке SQL Server.

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

Смежные вопросы