2010-03-26 62 views
3

我在應用程序的實時系統上觀察Profiler,並且看到有一條更新指令,我們定期運行(每秒)的速度非常慢。它每次花費大約400毫秒。 該查詢包括此更新(這是慢的部分)帶有索引的更新表太慢

UPDATE BufferTable 
    SET LrbCount = LrbCount + 1, 
    LrbUpdated = getdate() 
WHERE LrbId = @LrbId 

這是表

CREATE TABLE BufferTable(
    LrbId [bigint] IDENTITY(1,1) NOT NULL, 
     ... 
    LrbInserted [datetime] NOT NULL, 
    LrbProcessed [bit] NOT NULL, 
    LrbUpdated [datetime] NOT NULL, 
    LrbCount [tinyint] NOT NULL, 
) 

該表具有2個索引(非唯一的和非聚集的)與由該順序的字段:
* 的Index1 - (LrbProcessed,LrbCount)
* 索引2 - (LrbInserted,LrbCount,LrbProcessed)

當我看着這個時,我認爲這個問題來自Index1因爲LrbCount變化很大,它改變了索引中數據的順序。
但是在取消激活後index1我看到查詢與最初的時間相同。 然後我重建index1和desactivated index2,這次查詢速度非常快。

在我看來,索引2應該更新更快,數據的順序不應該改變,因爲LrbInserted時間沒有改變。

有人可以解釋爲什麼索引2是重得多更新然後索引1

謝謝!

編輯

我才意識到我是假設錯誤的事情。
完整的查詢有另一部分負責延遲:

DECLARE @LrbId as bigint 
SELECT TOP 1 @LrbId = LrbId 
FROM Buffertable 
WHERE LrbProcessed = 0 
    AND LrbCount < 5 
ORDER BY LrbInserted 

所以,最有可能它是從SQL引擎一個錯誤的決定上哪個索引使用有關。
對不起,我感到困惑。我想我們可以關閉這個問題。

回答

3

有人可以解釋爲什麼index2比索引1重得多嗎?

index2要長得多:密鑰大小10字節(8 + 1 + 1),而不是2(1 + 1)

也許它不適合高速緩存和頁面查找是需要找到記錄。

你的桌子有多大?

你也可能要啓用I/O統計:

SET STATISTICS IO ON 

,運行查詢幾次,看看物理頁的數量在輸出讀取。

更新:

對於此查詢:

SELECT TOP 1 @LrbId = LrbId 
FROM Buffertable 
WHERE LrbProcessed = 0 
     AND LrbCount < 5 
ORDER BY 
     LrbInserted 

工作速度快,創建以下指標:

CREATE INDEX ix_buffertable_p_c_i ON BufferTable (LrbProcessed, lrbCount, LrbInserted) 

,並重新編寫查詢:

WITH cts (cnt) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT cnt + 1 
     FROM cts 
     WHERE cnt < 5 
     ) 
SELECT TOP 1 bt.* 
FROM cts 
CROSS APPLY 
     (
     SELECT TOP 1 bti.* 
     FROM BufferTable bti 
     WHERE LrbProcessed = 0 
       AND LrbCount = cts.cnt 
     ORDER BY 
       LrbInserted 
     ) bt 
ORDER BY 
     LrbInserted 
+0

...並且不要忘記更新您的表的統計信息,或者優化器可能會根據過時的信息選擇效率較低的路徑。這對於數據庫迅速增長或高週轉率非常重要。 – DaveE 2010-03-26 15:46:19

+0

我對這個假設完全錯了,(我編輯了這個問題)。但更新統計數據可能很重要。 – pauloya 2010-03-26 15:59:39

+0

@Quassnoi,順便說一下,表格有833020行。 – pauloya 2010-03-26 16:00:02

0

在LrbId上有索引,還是主鍵?如果不是,增加一個應該可以改善一般的更新。

請注意,如果您在不同會話中獲得多個更新,則更新可能會修改索引時發生一些併發問題。如同Quassnoi提到的那樣,索引2也更新更新。