2015-08-19 76 views
1

我正在運行SQL Server 2012,這一個查詢正在殺死我的數據庫性能。SQL Server 2012:選擇和更新在一個查詢性能下降

我的文本消息提供程序不支持排定的文本消息,所以我有一個文本消息引擎從數據庫中拾取消息並在預定時間發送它們。我把這個查詢放在一起,從數據庫中獲取消息,並改變它們的狀態,使它們不會再被拾取。

查詢工作正常,它只是造成CPU的等待時間,特別是因爲它每隔一秒運行一次。我安裝了一個數據庫性能軟件,它說這個查詢佔了實例執行時間的92%。該軟件還表示,每一次執行都會執行347,267次邏輯讀取。

關於如何使這個表現更好的任何想法?

我應該在返回它們之前選擇一個臨時表並更新這些結果嗎?

下面是當前查詢:

UPDATE TOP (30) dbo.Outgoing 
    SET Status = 2 
    OUTPUT INSERTED.OutgoingID, INSERTED.[Message], n.PhoneNumber, c.OptInStatus 
    FROM dbo.Outgoing o 
    JOIN Numbers n on n.NumberID = o.NumberID 
    LEFT JOIN Contacts c on c.ContactID = o.ContactID 
    WHERE Scheduled <= GETUTCDATE() AND SmsId IS NULL AND Status = 1 

下面是執行計劃 ExecutionPlan

有三個表參與此查詢:傳出,數字,&聯繫

傳出是這個查詢處理的主表。目前只有兩個索引,OutgoingID [PK,bigint,not null]上的集羣主鍵索引和SmsId [varchar(255),null]上的非集羣非唯一索引,這是從我們的短信提供商一旦消息在他們的系統中成功接收。狀態列只是一個整數列,涉及幾種不同的狀態(計劃,排隊,發送,失敗等)

數字只是一個簡單的表格,我們存儲唯一的手機號碼,一些不同的格式,以及標識客戶的一些基本信息,例如名字,運營商等。它僅在NumberID [bigint]上具有羣集主鍵索引。 PhoneNumber列只是一個varchar(15)。

聯繫人表僅將個人(電話號碼)連接到我們的某個商家,並跟上號碼的選擇狀態以及與客戶/商家關係相關的其他信息。與此相關的查詢的列有OptInStatus [位,不爲空]和使用ContactID [PK,BIGINT NOT NULL]

--UPDATE--

加上了一個非聚集索引帶有列(Scheduled,SmsId,Status)的Outgoing表,這似乎將執行時間從2秒減少到了毫秒。我會在明天檢查我的性能監視軟件,看看它是如何改進的。感謝大家迄今爲止的幫助!

+4

查詢的執行計劃是什麼?這裏的表格模式是什麼?你在Numbers和Outgoing上有哪些索引? –

+2

我猜你需要'(狀態,預定)'或可能'(狀態,預定,數字ID)'索引。 – RBarryYoung

+2

沒有'ORDER BY',你的'TOP 30'是不安全的。如果超過30個符合您的標準的記錄,您可能不會更新您希望更新的30個記錄。 – alroc

回答

1

正如一些評論者已經指出的那樣,你需要在dbo.Outgoing表的新指標。服務器正在努力尋找要更新/輸出的行。這是最有可能問題出在哪裏:

WHERE Scheduled <= GETUTCDATE() AND SmsId IS NULL AND Status = 1 

爲了提高性能,你應該dbo.Outgoing創建索引,你包括這些列。這將使Sql Server更容易找到正確的行。另一方面,它會爲實際更新創建更多的工作,因爲在更新時會有一個需要注意的新索引。

當你正在處理這個問題時,除非你真的需要255個字符長,否則縮短SmsId列可能是個好主意。最好在創建索引之前。

作爲一種替代解決方案,您可能會考慮爲傳出的郵件分配不同的表格,並且這些郵件是已經過期的。然後,你可以:

  • 插入從OutgoingOutgone
  • 所有記錄Outgoing刪除所有的記錄,產量子句像你現在正在做。

確保雖然該insertdelete操作在一個事務中完成或你很快就會在數據庫中怪異的不一致。

0

它只是造成CPU的等待時間,特別是因爲它每隔一秒運行一次。

擺脫TOP 30和少得多往往比每隔一秒......也許每兩三分鐘運行一次。

+0

提供者擁有自己的隊列,這是一個簡單的先進先出隊列,但我的隊列會爲更重要的消息加權以獲得優先級。提供商能夠每秒發送30條消息,這就是爲什麼我每隔30秒就得到30條消息的原因。並非所有消息都通過此隊列運行,有些仍然直接通過提供程序,因此我不能使隊列過飽和。短信是時間敏感的,所以他們需要儘快出去,甚至等待5秒鐘是不可接受的。如果有任何事情需要更頻繁地運行而不是更少。 – JoeyZero

-2

你可以讓您的SQL Server的最大並行度更快的處理