Я использую 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 все еще жив.
Звучит довольно странно, вы проверили с профилировщиком, что делает Subsonic? Вызывается ли SP так же, как и вручную? – VladV
Попробуйте перетащить данные из содержимого, попавшего в таблицу temp, а затем сделайте полный запрос о присоединении к другим таблицам. – Paul