我想获得一些关于 SQL Server 删除行为的额外见解/推理。我们有一个相当大的数据库,超过 1800 GB。
其中有一些非常浅的表(只有几个整数列)有数百万行。当我们从这些浅表中删除 10,000 行时,删除查询通常非常快(最多几秒钟)。
我们还有一个表,其中的字段类型image
存储平均 100 KB 的图像。当我们从这个表中只删除几千行时,需要一分钟多的时间。
虽然区别很明显(删除了更多的数据大小),但我很想了解更多关于 SQL Server 内部发生的事情。这样我就可以更好地理解后者的删除速度要慢得多。
任何人都可以请说明一下吗?
Rem*_*anu 10
删除了更多的数据大小
删除 100kb 的image
blob 实际上不是数据大小的操作。该 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 候选行的索引、触发器正在运行等。链接的方法将帮助您查明原因。