sql-server - 用索引更新表太慢

标签 sql-server performance indexing

我在我们应用程序的实时系统上观察 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)
* Index2 - (LrbInserted, LrbCount, LrbProcessed)

当我看到这个时,我认为问题可能来自 Index1,因为 LrbCount 变化很大,它改变了索引中数据的顺序。
但是在停用 index1 之后,我看到查询所花的时间与最初相同。 然后我重建了index1并停用了index2,这次查询非常快。

在我看来 Index2 应该更新得更快,数据的顺序不应该改变,因为 LrbInserted 时间没有改变。

有人能解释一下为什么 index2index1 更难更新吗?

谢谢!

编辑

我刚刚意识到我的假设是错误的。
完整的查询还有另一部分负责延迟:

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

所以,这很可能与 Sql 引擎对使用哪个索引的错误决定有关。
对困惑感到抱歉。我想我们可以结束这个问题了。

最佳答案

Can someone explain why index2 is much heavier to update then index1?

index2 长得多: key 大小是 10 字节 (8 + 1 + 1) 而不是 2 (1 + 1)

可能它不适合缓存,需要页面查找来定位记录。

你的 table 有多大?

您可能还想启用 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

关于sql-server - 用索引更新表太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2524234/

相关文章:

SQL 查询未返回预期结果

.net - 测量触发的事件数量?

.net - 用于性能基准测试的 Visual Studio 加载项

Mysql 8列索引

indexing - Hash 和 Skiplists 索引并行吗?

sql - 从日期集中获取日期范围间隙

SQL Server - 包含 FOR XML 要求的无效 XML 标识符;

sql - 如何使用 SQL Server 在单行中根据每个用户每周的周末结束日期获取前 2 条记录

python - 循环列表列表而不嵌套太多

java - 优化 XML 规范化方式