我正在我们的应用程序的实时系统上观看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时间没有改变,所以数据的顺序不应该改变。
有人可以解释为什么 index2 更新然后更强 index1 ?
谢谢!
编辑
我刚才意识到我做错了。
完整查询还有另一部分负责延迟:
DECLARE @LrbId as bigint
SELECT TOP 1 @LrbId = LrbId
FROM Buffertable
WHERE LrbProcessed = 0
AND LrbCount < 5
ORDER BY LrbInserted
所以,很可能它与Sql引擎关于使用哪个索引的错误决定有关 对困惑感到抱歉。我想我们可以关闭这个问题。
答案 0 :(得分:3)
有人可以解释为什么index2比index1更重要吗?
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
答案 1 :(得分:0)
LrbId上有索引,还是主键?如果没有,添加一个通常可以改善更新。
请注意,如果您在不同的会话中获得多个更新,则可能会出现一些并发问题,因为更新会修改索引。
如Quassnoi所述,索引2的更新也更大。