SQL Server中sp_spaceused统计数据使用的空间总量不正确的原因
很多时候,我们经常使用sp_spaceused来查看表的空间使用情况,上个月群里有个网友说他使用DELETE删除了数据后,使用sp_spaceused查看,发现该表的分配的空间总量(reserved)与数据使用的空间总量(data)没有变化,当时和他讨论了并分析了一下原因,随手记录了一下这个案例,这个周末刚好有点时间,正好分析整理一下这个案例、分享在这篇文章。如下所示,我们先构造数据,我们的测试案例比较极端,刚刚保证每个页面(page)刚好存储两条记录。如下所示:
USE Test ;
GO
CREATE TABLE space_test
(
id INT,
name VARCHAR(4000)
)
GO
SET NOCOUNT ON;
Go
DECLARE @Index INT ;
SET @Index = 1;
WHILE @Index <= 10000
BEGIN
INSERT INTO dbo.space_test
SELECT @Index, REPLICATE(N'k', 4000);
SET @Index += 1;
END
EXEC sp_spaceused 'dbo.space_test'


接下来我们删除了id为偶数的记录。
DELETE dbo.space_test WHERE id %2=0
如下截图所示,我们删除了5000条记录,还剩下5000条记录,但是该表的分配的空间总量(reserved)与数据使用的空间总量(data)没有变化,依然是40008KB和40000KB

我们删除了一半记录,照理说,数据使用的空间总量(data)应该变化了。那么我使用DBCC SHOWCONTIG('space_test')来看看,如下截图所示,
你会发现每页的平均可用字节数(Avg. Bytes Free per Page) 和平均页密度(满)(Avg. Page Density (full))出现了变化。如下对比所示:
|
|
Avg. Bytes Free per Page |
Avg. Page Density (full) |
|
删除前 |
62 |
99.23% |
|
删除后 |
4077.8 |
49.62% |

我们知道sp_spaceused的精确单位是页。它是根据sys.allocation_units 和sys.partitions 这两张管理视图来计算存储空间的。有时候,这两张表可能不能及时反映出数据的准确信息。可以通过updateusage这个参数,要求SQL Server为这个指令更新管理视图里的统计信息。但是这个案例中,sp_spaceused不准确的原因并不是因为这两张表没有及时反映出数据的准确信息,而是实验中按照特殊规律,在每一页都删除一条记录,保留一条记录,导致每一页上释放了接近一半的空间,并且页的填充程度接近50%,从而出现页面碎片化非常严重的情况,而sp_spaceused的精确单位是页,从而导致这种特殊的情况出现。
其实这个倒没有必要大惊小怪,这个空间虽然没有释放,但是下次依然可以再次利用,就好比一列火车,每节车厢只载了一半乘客,后面的路程中,可以继续往里面加入新的乘客。如下所示我们插入5000条记录,你会发现页的平均密度变化了,之前空闲的空间被重新利用了。
DECLARE @Index INT ;
SET @Index = 2;
WHILE @Index <= 10000
BEGIN
INSERT INTO dbo.space_test
SELECT @Index, REPLICATE(N'k', 4000);
SET @Index += 2;
END
GO

SQL Server中sp_spaceused统计数据使用的空间总量不正确的原因的更多相关文章
- .SQL Server中 image类型数据的比较
原文:.SQL Server中 image类型数据的比较 在SQL Server中如果你对text.ntext或者image数据类型的数据进行比较.将会提示:不能比较或排序 text.ntext 和 ...
- 删除sql server中重复的数据
原文:删除sql server中重复的数据 with list_numbers as( select Name, AuthorOrTime, Url, Price, EstimatePrice, Si ...
- sql Server中临时表与数据表的区别
sql server 中临时表与数据表的区别 1.如何判断临时表和数据表已生成 --如何判断临时表是否已创建--- if exists(select * from tempdb..sysobjects ...
- 转:Sql Server中清空所有数据表中的记录
如果要删除数据表中所有数据只要遍历一下数据库再删除就可以了,清除所有数据我们可以使用搜索出所有表名,构造为一条SQL语句进行清除了,这里我一一给各位同学介绍. 使用sql删除数据库中所有表是不难的 ...
- SQL Server中Table字典数据的查询SQL示例代码
SQL Server中Table字典数据的查询SQL示例代码 前言 在数据库系统原理与设计(第3版)教科书中这样写道: 数据库包含4类数据: 1.用户数据 2.元数据 3.索引 4.应用元数据 其中, ...
- Sql Server中清空所有数据表中的记录
Sql Server中清空所有数据表中的记录 清空所有数据表中的记录: 代码如下:exec sp_msforeachtable @Command1 ='truncate table ?'删除所有数据 ...
- 通过DBCC Page查看在SQL Server中哪行数据被锁住了?
原文:通过DBCC Page查看在SQL Server中哪行数据被锁住了? 如何查看被锁的是哪行数据?通过dbcc page可以. 要想明白这个问题: 首先,需要模拟阻塞问题,这里直接模拟了阻塞问题的 ...
- 从TXT文本文档向Sql Server中批量导入数据
下面我们通过以下的简单的SQL语句即可实现数据的批量导入,代码如下: Bulk insert id From 'G:\文档\test.txt' With ( fieldterminator=',', ...
- (4.31)sql server中的xml数据操作
关键词:xml数据转为行列方式显示 常规案例: declare @data xml declare @h int set @data=' <bookstore> <row> & ...
随机推荐
- Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 上一篇总结了下ArrayList .LinkedList和Vector比较,今天泥瓦匠总结下Hash ...
- ftp服务器搭建及简单操作
ftp服务器搭建及简单操作 1. 添加一个新用户,使用名useradd testftp,然后使用passwd testftp对新添加的用户设置密码(这里设置为“1234567”). 2. 安装ftp服 ...
- You must reset your password using ALTER USER statement before executing this statement.
MySQL 5.7之后,刚初始化的MySQL实例要求先修改密码.否则会报错: mysql> create database test; ERROR 1820 (HY000): You must ...
- python字符串(string)方法整理
python中字符串对象提供了很多方法来操作字符串,功能相当丰富. print(dir(str)) [..........'capitalize', 'casefold', 'center', 'co ...
- 快速制作gif动图
0.环境准备 gif动画录制工具,下载后可以直接安装: 安装提示需要.net framework4.0.30319环境的话,下载一个直接安装即可 1.开始录制 安装成功界面: 开始录制: 录制效果如下 ...
- js_jquery_创建cookie有效期问题_时区问题
用jquery设置Cookie过期的两种方式: $.cookie('名', '值', { expires: 过期时间(DateTime), path: "/", domain: w ...
- [转]angular2: including thirdparty js scripts in component
本文转自:https://stackoverflow.com/questions/35570746/angular2-including-thirdparty-js-scripts-in-compon ...
- JDBC&Hibernate
当数据库有大量用户来访问要采取什么技术解决 可以采用连接池: 什么是ORM 对象关系映射(Object Relational Mapping 简称ORM)是一种为了解决面向对象与面向关系数据库存在的互 ...
- ASP.NET登录验证
protected void btnLogin_Click(object sender, EventArgs e) { string username = txtUserName.Value.Trim ...
- 修改tomcat命令黑窗口的名字
一.为什么要修改tomcat黑窗口的名字 同时启动多个tomcat时,不好区分,而给tomcat的命令窗口取名区分是个不错的选择,例如下面这个效果. 二.修改的方法 1.找到tomcat的bin目录下 ...