一般情况下,如果我们在sql server中删除大量的数据后,数据库中的数据减少,那么应该提升sql server的性能才对,可今天我们看一个案例,在这个案例中,情况是相反的,
使用Delete删除大量数据后SQL Server性能下降的问题。
问题描述:1,使用delete删除大量数据后数据的性能下载。
2,原来一些存储过程的执行时间为20分钟左右,删除数据后执行时间需要2-3个小时。
背景信息:1,通过delete在数据库中删除了大量的数据。
2,数据删除后,客户也进行了相关的维护工作,如重建索引,更新统计信息等。
3,性能变慢的存储过程是对表做很多的delete,insert,select的操作。
问题的调查:1,相关的表都是堆(heap table)
2,这些表中并没有很多的数据
3,对表进行dbcc checkcontig扫描发现表很大,但页的密度(Page Density)却很小
扫描数据如下:DBCC SHOWCONTIG 正在扫描 '……' 表...
表: '……' (7983405);索引 ID: 1,数据库 ID: 5
已执行 TABLE 级别的扫描。
- 扫描页数................................: 1
- 扫描区数..............................: 1
- 区切换次数..............................: 0
- 每个区的平均页数........................: 1.0
- 扫描密度 [最佳计数:实际计数].......: 100.00% [1:1]
- 逻辑扫描碎片 ..................: 0.00%
- 区扫描碎片 ..................: 0.00%
- 每页的平均可用字节数........................: 7997.0
- 平均页密度(满).....................: 1.20%
DBCC SHOWCONTIG 正在扫描 '……' 表...
表: '……' (11667635);索引 ID: 1,数据库 ID: 5
已执行 TABLE 级别的扫描。
- 扫描页数................................: 1
- 扫描区数..............................: 1
- 区切换次数..............................: 0
- 每个区的平均页数........................: 1.0
- 扫描密度 [最佳计数:实际计数].......: 100.00% [1:1]
- 逻辑扫描碎片 ..................: 0.00%
- 区扫描碎片 ..................: 0.00%
- 每页的平均可用字节数........................: 8025.0
- 平均页密度(满).....................: 0.85%
问题产生原因:1,当表上有聚集索引时,删除操作会释放空页。然而,从堆中删除行时,数据库引擎可以使用行锁定或页锁定进行操作。结果,删除操作导致的空页将继续分配给堆。未释放空页时,数据库中的其他对象将无法重用关联的空间。
2,虽然表中没有大量数据,但是它们拥有大量的几乎为空的数据页。扫描表因此变得十分花时间。
解决方案:若要删除堆中的行并释放页,我们可以使用下列方法中的一种。
1,在DELETE语句中指定TABLOCK提示。使用TABLOCK命令会导致删除操作获取表的共享锁,而不是行锁或页锁。这将允许释放页。
2,如果要从表中删除所有行,可使用TRUNCATE TABLE代替Delete
3,删除行之前,请对堆创建聚集索引。删除行之后,可以删除聚集索引。与前面的方法相比,此方法非常耗时,并且使用更多的临时资源。s
来源:http://blogs.msdn.com/b/apgcdsd/archive/2011/12/06/delete-sql-server.aspx
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!