SQL Server 慢 DELETE 请求的解释

8 performance sql-server

我想获得一些关于 SQL Server 删除行为的额外见解/推理。我们有一个相当大的数据库,超过 1800 GB。

其中有一些非常浅的表(只有几个整数列)有数百万行。当我们从这些浅表中删除 10,000 行时,删除查询通常非常快(最多几秒钟)。

我们还有一个表,其中的字段类型image存储平均 100 KB 的图像。当我们从这个表中只删除几千行时,需要一分钟多的时间。

虽然区别很明显(删除了更多的数据大小),但我很想了解更多关于 SQL Server 内部发生的事情。这样我就可以更好地理解后者的删除速度要慢得多。

任何人都可以请说明一下吗?

Rem*_*anu 10

删除了更多的数据大小

删除 100kb 的imageblob 实际上不是数据大小的操作。该 blob 被释放,而不是被删除,并且没有完整的图像日志记录。您可以轻松测试:

create database blob
go

use blob
go

create table t (id int not null identity(1,1), blob image)
go

insert into t (blob) values (
  replicate(
    cast(0x000102030405060708090a0b0c0d0e0f as varbinary(max)), 
    100*1024/16))
go 10

alter database blob set recovery full
go

backup database blob to disk='nul:'
go

delete from t where id = 3
go

select * from fn_dblog(null, null)
go
Run Code Online (Sandbox Code Playgroud)

您将看到的日志记录将类似于以下内容:

00000026:0000008e:0001  LOP_BEGIN_XACT  LCX_NULL    0000:00000304   0x0000  76  124
00000026:0000008e:0002  LOP_LOCK_XACT   LCX_NULL    0000:00000304   0x0000  24  56
00000026:0000008e:0003  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0004  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0005  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0006  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0007  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:0008  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0009  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:000a  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:000b  LOP_MODIFY_ROW  LCX_PFS     0000:00000304   0x0000  62  92
00000026:0000008e:000c  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
...    
00000026:0000008e:0022  LOP_HOBT_DELTA  LCX_NULL    0000:00000304   0x0000  64  64
00000026:0000008e:0023  LOP_DELETE_ROWS LCX_TEXT_MIX    0000:00000304   0x0000  62  172
00000026:0000008e:0024  LOP_DELETE_ROWS LCX_HEAP    0000:00000304   0x0000  62  120
00000026:0000008e:0025  LOP_COMMIT_XACT LCX_NULL    0000:00000304   0x0000  80  84
Run Code Online (Sandbox Code Playgroud)

如您所见,包含该image列的行没有包含 +102400 字节数据的“DELETE”记录。有一堆解除分配(PFS/IAM/GAM 操作)和一个简单的行删除(在我的情况下,如果我记得将 ID 声明为 PK,B-Tree 的堆看起来非常相似......)。有关更多详细信息,请参阅如何读取和解释 SQL Server 日志

这留下了原始问题:为什么一个删除比另一个慢?我建议您阅读如何分析 SQL Server 性能。按照描述的方法来捕获对特定语句的等待并查看原因是什么。参见分析单个查询执行,特别是关于分析单个查询执行等待时间的部分。只有在您测量之后,我们才能解开谜语。可能有很多因素:由于 blob 表上的并发读取而导致更多阻塞、缺少用于在一个表上定位 DELETE 候选行的索引、触发器正在运行等。链接的方法将帮助您查明原因。