我们有一个大型数据库,大约1TB,在功能强大的服务器上运行SQL Server 2014。几年一切正常。大约2周前,我们进行了全面维护,其中包括:安装所有软件更新;重建所有索引和紧凑的数据库文件。但是,我们没想到在实际负载相同的情况下,在某些阶段数据库的CPU使用率会增加100%以上至150%。
经过大量的故障排除后,我们将其范围缩小到一个非常简单的查询,但找不到解决方案。查询非常简单:
select top 1 EventID from EventLog with (nolock) order by EventID
它总是需要约1.5秒!但是,带有“ desc”的类似查询始终大约需要0毫秒:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable大约有5亿行;EventID
是ASC
数据类型为bigint(标识列)的主聚集索引列(有序)。有多个线程在顶部的数据表中插入数据(较大的EventID),有1个线程从底部的数据表中删除数据(较小的EventID)。
在SMSS中,我们验证了两个查询始终使用相同的执行计划:
聚集索引扫描;
估计行数和实际行数均为1;
估计的执行次数和实际的执行次数均为1;
估计I / O成本为8500(似乎很高)
如果连续运行,则两者的查询成本都是相同的50%。
我更新了索引统计信息with fullscan
,问题仍然存在;我再次重建了索引,问题似乎消失了半天,但又回来了。
我通过以下方式打开了IO统计信息:
set statistics io on
然后连续运行两个查询,发现以下信息:
(对于第一个查询,慢速查询)
表“ PTable”。扫描计数1,逻辑读407670,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
(对于第二个查询,快速查询)
表“ PTable”。扫描计数1,逻辑读4,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
注意逻辑读取的巨大差异。在两种情况下都使用索引。
索引碎片可以解释一下,但是我相信影响很小。问题从未发生过。另一个证明是,如果我运行如下查询:
select * from EventLog with (nolock) where EventID=xxxx
即使我将xxxx设置为表中最小的EventID,查询也总是快如闪电。
我们检查了,没有锁定/阻塞问题。
注意:我只是试图简化上面的问题。“ PTable”实际上是“ EventLog”;的PID
是EventID
。
我得到了没有NOLOCK
提示的相同结果测试。
有人可以帮忙吗?
XML中更详细的查询执行计划,如下所示:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
我认为提供create table语句并不重要。它是一个旧数据库,已经运行了很长时间,直到进行维护为止。我们自己做了很多研究,并将其范围缩小到我的问题中提供的信息。
该表通常是使用EventID
列作为主键创建的,该identity
列是type 的列bigint
。这时候,我想问题出在索引碎片上。重建索引后,问题似乎已经消失了半天。但是为什么它这么快回来...?