Tif*_*nyP 17 performance sql-server select sql-server-2014 top query-performance
我们有一个大约 1TB 的大型数据库,在强大的服务器上运行 SQL Server 2014。几年来,一切都运行良好。大约 2 周前,我们进行了全面维护,其中包括: 安装所有软件更新;重建所有索引和压缩 DB 文件。但是,我们没想到在某个阶段,在实际负载相同的情况下,DB 的 CPU 使用率会增加超过 100% 到 150%。
经过大量的故障排除,我们将其缩小到一个非常简单的查询,但我们找不到解决方案。查询非常简单:
select top 1 EventID from EventLog with (nolock) order by EventID
Run Code Online (Sandbox Code Playgroud)
它总是需要大约 1.5 秒!但是,使用“desc”的类似查询总是需要大约 0 毫秒:
select top 1 EventID from EventLog with (nolock) order by EventID desc
Run Code Online (Sandbox Code Playgroud)
PTable 大约有 5 亿行;EventID
是ASC
数据类型为 bigint(身份列)的主聚集索引列(ordered )。顶部有多个线程向表中插入数据(较大的 EventID),底部有 1 个线程删除数据(较小的 EventID)。
在 SMSS 中,我们验证了两个查询始终使用相同的执行计划:
聚集索引扫描;
估计行数和实际行数均为1;
估计和实际执行次数均为1;
估计I/O成本是8500(好像有点高)
如果连续运行,则两者的查询成本相同 50%。
我更新了索引统计with fullscan
,问题依旧;我再次重建索引,问题似乎消失了半天,但又回来了。
我打开了 IO 统计:
set statistics io on
Run Code Online (Sandbox Code Playgroud)
然后连续运行两个查询并找到以下信息:
(对于第一个查询,较慢的)
表'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
Run Code Online (Sandbox Code Playgroud)
即使我将 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
类型为 的列bigint
。这时候,我猜测问题出在索引碎片上。索引重建后,问题似乎消失了半天;但是为什么这么快就回来了……?
Pau*_*ite 18
聚集索引扫描显示 423,723 次逻辑读取返回第一行,耗时 1926 毫秒:
按索引顺序定位第一行似乎很多。
很可能您的幽灵清理任务运行很远,或者已经停止。您应该检查ghost_record_count
聚集索引sys.dm_db_index_physical_stats
并监视随时间的变化。
从索引末尾开始的有序扫描看到了不断的删除活动,在它找到要返回的第一个“活动”行之前,必须扫描大量的幻影记录。这解释了额外的逻辑读取。向下搜索 b 树到索引的最低值将遇到更少的幻影记录。
另一个影响性能的因素是扫描本身负责删除存储引擎内部: Paul Randal 的深度幽灵清理中提到的幽灵记录。
您应该检查跟踪标志 661(禁用重影清除)是否处于活动状态。
PAGLOCK
提示,可以在现场启用ghost清理,这也可以很好地解决问题。如果 Ghost 清理过程已完全停止,最有效的解决方案通常是重新启动 SQL Server 实例。您还应该确保 SQL Server 正在运行最新的累积更新之一。多年来,出现了许多幽灵清理错误。
在您的具体情况下:
原来问题是由同一台服务器上的另一个测试数据库引起的。该测试数据库因“数据丢失”而恢复,并且已损坏。令人惊讶的是,幽灵清理过程显然卡在了该数据库中。一旦我们从 SMSS 中删除了损坏的数据库,问题就自行解决了(花费了很长时间,可能导致 DB 暂时锁定)。
归档时间: |
|
查看次数: |
4713 次 |
最近记录: |