2010-06-10 72 views
2

我在Windows Server 2008 R2上使用SQL Server 2008,所有這些都已啓動。SQL Server鎖定/掛起問題

我偶爾會遇到SQL Server在我們的活動服務器上100%的CPU使用率懸掛問題。在發生這種情況時,似乎SQL Sever上的所有等待時間都發送給SOS_SCHEDULER_YIELD。

這是導致掛起的存儲過程。我已經添加了「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命中一分鐘任何它被擊中相當頻繁)。所以很明顯,這張表是問題的根源。有一個存儲過程被調用來將命中軌道添加到ContentHit表中,它非常簡單,它只是從傳入的參數中構建一個字符串,其中包含來自某些查找表的幾個選擇,然後是主插入:

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

ContentHit表的ID列上有一個聚集索引,並且我在CreatedDate上添加了另一個索引,因爲在select中使用了這個索引。

當我分析問題時,我看到存儲過程正好執行了30秒,然後發生SQL超時異常。如果它有所作爲,使用它的Web應用程序是ASP.NET,並且我使用Subsonic(3)來執行這些存儲的特效。

有人能告訴我如何最好地解決這個問題嗎?我不在乎讀髒數據...

編輯: MostPopularRead存儲過程很少被稱爲 - 它在網站的主頁上調用,但結果被緩存了一天。我看到的事件模式是當我清除緩存時,主站點發出多個請求,並且它們都會觸發存儲的proc,因爲它尚未被緩存。 SQL Server然後最大化,並且只能通過重新啓動sql server進程來解決。當我這樣做時,通常proc會執行OK(約200毫秒)並將數據放回緩存中。

編輯2: 我檢查了執行計劃,並且查詢看起來很有聲音。正如我之前說過的那樣,它只需要大約200毫秒的時間來執行。我在選擇語句中添加了MAXDOP 1,強制它只使用一個CPU內核,但我仍然看到這個問題。當我觀察等待時間時,我發現XE_DISPATCHER_WAIT,ONDEMAND_TASK_QUEUE,BROKER_TRANSMITTER,KSOURCE_WAKEUP和BROKER_EVENTHANDLER正在佔用大量的等待時間。

編輯3: 我以前認爲這與subsonic,我們的ORM有關,但切換到ADO.NET,erros仍然是活的。

+0

聽起來很奇怪,你是否與Profiler檢查了Subsonic的作用? SP的調用方式與手動完全相同嗎? – VladV 2010-06-11 07:00:49

+0

嘗試將內容匹配中的數據拖到臨時表中,然後在加入其他表時進行完整查詢。 – Paul 2017-05-03 07:39:15

回答

2

Remove the NOLOCK hint

在SSMS中打開查詢,運行SET STATISTICSIO ON並在該過程中運行查詢。讓它完成並在這裏發佈IO統計信息。然後發佈表格定義及其上定義的所有索引。然後有人可以用你需要的適當索引進行回覆。

與所有SQL性能問題一樣,如果沒有完整的模式定義,查詢文本在很大程度上是不相關的。

瞎猜一個覆蓋索引是:

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

更新

XE_DISPATCHER_WAITONDEMAND_TASK_QUEUEBROKER_TRANSMITTERKSOURCE_WAKEUPBROKER_EVENTHANDLER:您可以放心地忽略這些等待。它們顯示出來是因爲它們表示線程駐留並等待分派XEvents,Service Broker或內部SQL線程池工作項目。由於他們大部分時間都在停車等待,所以他們被認爲是不切實際的等待時間。別理他們。

+0

感謝Remus。但正如我前面所說,當我運行查詢時,它運行得非常有效(200毫秒),除非它掛起,所以我不希望有其他索引可以解決這個問題。您添加的索引是我添加到該表中的索引。 如果我的Subsonic ORM測試沒有透露任何信息,我會發布此信息。 – 2010-06-10 22:14:02

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多久調用一次,需要多長時間才能執行? 查詢中的聚合可能相當耗費CPU資源,特別是在存在大量數據和/或無效索引的情況下。所以,你可能會面臨高CPU壓力 - 基本上,對CPU時間的需求太高。

我會考慮以下幾點:

  1. 檢查什麼其他的查詢執行時的CPU是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 ISOLATION LEVEL READ UNCOMMITTED而不是向每個表添加(nolock)更容易。

+0

我同意這個答案。嘗試調整最大並行度。具有諷刺意味的是,我已經看到了降低max dop可以提高性能的情況。 – 2010-06-10 13:33:12

+0

好的,謝謝我將着手研究MAXDOP並瞭解CPU在100%時發生的情況。 – 2010-06-10 14:54:19

+0

MostPopularRead一旦被調用就被緩存,所以不應該經常調用。但是,由於這個問題,當站點正在等待MostPopularRead執行以便它可以被緩存時,會加載更多請求並觸發存儲過程 - 這是SQL Server掛起時的情況。 如果我從管理工作室手動運行存儲過程,它永遠不會超過0.5秒,通常約爲200毫秒。 – 2010-06-10 14:56:23

0

默認情況下,sql server會針對所有查詢(最大DoP設置>高級屬性,DoP =併發度)使用所有核心/ CPU,即使只有一個內核實際上正在等待某些內核I/O。
如果你搜索網絡或本網站,你會發現解釋它比我更好的資源(比如監視你的I/O,儘管你看到一個CPU綁定的問題)。
在一臺服務器上,我們無法更改具有鎖定所有資源(CPU)的錯誤查詢的應用程序,但通過將DoP設置爲我們管理的核心數量的一半來避免服務器「停止」。在我們的案例中,對查詢不太平行的影響可以忽略不計。

-
大教堂

0

感謝所有發佈的人,我獲得了一些很棒的SQL Server性能調優技巧。最後,我們耗盡時間來解決這個謎團 - 我們發現了一種更有效的方法來收集這些信息並將它緩存在數據庫中,因此這解決了我們的問題。