2010-03-26 60 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也更新更新。