《SQL Server企业级平台管理实践》读书笔记——SQL Server中数据文件空间使用与管理

1、表和索引存储结构

在SQL Server2005以前,一个表格是以一个B树或者一个堆(heap)存放的。每个B树或者堆,在sysindexes里面都有一条记录相对应。SQL Server2005以后,引入了分区表的概念(Table Partition),在存储组织上,现有的分区基本上替代了原来表格的概念,原先表的概念成为了一个逻辑概念。一个分区就是一个B树或者一个堆。而一张表格则是一个到多个分区的组合。

1.1用B树存储于聚集索引的表数据页

如果一个表格上有聚集索引(Clustered Index),数据行将基于聚集索引键按顺序存储。聚集索引按B树索引结构来实现,B树索引结构支持基于聚集索引键值对行快速检索。数据页面之间用双向链表,紧密相连。

1.2堆是没有聚集索引的表

如果表格上没有聚集索引,数据行将不按任何的顺序存储,数据页也没有任何特殊的顺序。数据页之间没有链表链接。

1.3非聚集索引

非聚集索引与聚集索引有一个相似的B树索引结构。不同的是,非聚集索引不影响数据行的顺序。叶级别仅包含索引行,没有完整的数据。每个索引行包含非聚集索引键值和行定位符。定位符指向(在另一个B树或者堆中)包含键值的数据行。非聚集索引本身也会占用一些数据页。这些页面以双向链表相连。

sys.partitions为表和索引提供一个对象,每个对象占据一行信息,其中分为以下几类:

1、index_id=0,这种行记录的是堆表信息

sys.system_internals_allocation_units中的first_iam_page列指向指定分区中堆数据页i聚合的IAM链。因为这些页没有连接,不可能从第一页找到下一页,所以SQL Server只能使用IAM页查找数据页集合中的每一页。

2、index_id=1,表示表或视图的聚集索引

sys.system_internals_allocation_units中的root_page列指向指定分区内聚集索引B树的顶端。SQL Server使用索引B树链表能够从顶端页面查找到分页中的每个数据页。

3、index_id>1,为表或视图创建的非聚集索引

sys.system_internals_allocation_units中的root_page列指向指定分区内非聚集索引B树的顶端。

如果存在LOB列(image、varchar(max)、text)的每个表在sys.partitions中也另外再有一行,其index_id>250,用以管理LOB页面。

first_iam_page列指向管理LOB_DATA分配单元中的页的IAM页链。

总之,从一个对象Index_id就能判断出它是什么类型的存储方式,如果是0,据说明这张表没有聚集索引;如果是1,就是聚集索引页面;如果大于250,就是text或image字段;如果在2——250之间,就是非聚集索引页面。

堆结构

堆是不包含聚集索引的表。SQL Server使用“索引分配映射(IAM)”页将堆的页面联系在一起。堆的特点有以下几个:

1、堆内的数据页和行没有任何特定的顺序。

在一个堆里的数据完全是随机存放的。而且SQL Server也假设数据之间没有任何联系。

2、页面也不连接在一起

数据页之间唯一的逻辑连接是记录在IAM页内的信息。页面与页面之间也没有什么紧密的联系。

3、堆中的行一般不按照插入的顺序返回

因为IAM按数据页在数据文件内存在的顺序标示他们,所以这意味着堆扫描会沿每个文件进行。而不是按这些行的插入顺序,或者任何逻辑上的顺序。

下图,表现了SQL Server数据库引擎如何使用IAM页检索具有单个分区的堆中的数据行。

可以看到,SQL Server对堆的管理师比较简单的。在算法能力上也是比较脆弱的。不谈性能,光从数据存储管理上来讲,用堆去管理一个超大的表格是比较吃力的。所以在SQL Server里对于所有大的、经常使用的表格上都建立聚集索引。因为聚集索引会避免很多问题。

聚集索引结构

在SQL Server中,索引是按B树结构进行组织的。索引B树种的每一页称为一个索引节点。B树的顶端节点称为根节点。索引中的底层节点称为叶节点。根节点与叶节点之间的任何索引级别统称为中间级。每个索引行包含一个键值和一个指针,该指针指向B树上某一中间页或页级索引中的某个数据行。每级索引张的页均被链接在双向链表中。

数据链内的页和行将按聚集索引键值进行排序。所有插入操作都在所插入行中的键值与现有行中的排序顺序相匹配时执行。B树页集合由sys.system_internals_allocation_units系统视图中的页指针来定位。

对于某个聚集索引,sys.system_internals_allocation_units中的root_page列指向该聚集索引某个特定分区的顶部。SQL Server将在索引中向下移动以查找与某个聚集索引键对应的行。为了查找键的范围,SQL Server将在索引中移动以查找该范围的起始键值,然后用向前或向后指针在数据页中进行扫描。为了查找数据页链的首页,SQL Server将从索引的根节点沿最左边的指针进行扫描。

相对于堆,聚集索引的特点有以下几个:

1、堆内的数据页和行有严格的顺序。

聚集索引保证了表格的数据按照索引行的顺序排列。而且SQL Server知道这种顺序关系。

2、页面链接在一起。页面与页面联系紧密。

3、树种的行一般能够按照索引列的顺序返回。

所以从这几点来看,建立B树以后,SQL Sever对数据页的管理能够更加快速有效,有些发生在堆上的问题就不容易发生在B树上,性能高出很多

非聚集索引结构

非聚集索引与聚集索引具有相同的B树结构,他们之间的显著差别在于以下两点:

1、基础表的数据行不按非聚集键的顺序排序和存储

2、非聚集索引的页层是由索引页面不是由数据页组成

3、建立非聚集索引的表可以是一个B树,也可以是一个堆。

4、如果表示堆(意味着该表没有聚集索引),则行定位器是指向行的指针。该指针由文件标识符(ID)、页码和页上的行数生成。整个指针称为行ID(RID)。

5、如果表没有聚集索引或索引视图上有聚集索引,则行定位器是行的聚集索引键。如果聚集索引不是唯一的索引,SQL Server将添加在内部生成的值(称为唯一值)以使所有重复键唯一。SQL Server通过使用存储在非聚集索引的叶行内的聚集索引键搜索聚集索引来检索数据行。

所以非聚集索引不会去改变或改善数据页的存储方式。它的B数结构只针对自己的索引页面。如果问题是堆的特性导致的,加一个非聚集索引不能带来根本的改善。

对于表格建立聚集索引不会增加表格的大小,而增加非聚集索引就会增加空间,但是如果在一个经常变化的表格建立聚集索引,会容易遇到页拆分(page split),所以尽力聚集索引会影响性能。基于这种考虑,很多设计者不愿意在SQL Server的表格中建立聚集索引,但是一张不建立索引的表格性能是非常差的,所以就增加了非聚集索引,以期望得到好的性能。

但是这这种方案是一种浪费空间、性能也不一定好的设计,为此SQL Server2005做了个比较,得出的结论是:有聚集索引的表格在Select 、Update、Delete这些动作性能有很大的提升,更重要的是在Insert这一项上,两者没有什么差别。并没有出现聚集索引影响Insert速度的现象。所以再次强烈建议,在一个大的表格上一定要建立一个聚集索引。

DELETE和TRUNCATE之间的区别

1、DELETE命令并不能完全释放表格或索引的数据结构以及他们申请的页面,尤其在堆表上。在SQL Server2005以后的版本中树结构的数据对于页释放做的更好一点,但是也不能完全释放。而TRUNCATE就能完全释放掉

2、所用事务日志空间较少,因为DELETE语句每次删除一行,并在事务日志中为所删除的每行记录一个项,TRUNCATE TABLE通过释放用于存储数据的数据页来删除数据,并且在事务日志中只记录这个动作,而不记录每一行。

3、使用的锁通常较少,当使用行锁执行Delete语句时,将锁定表中各行以便删除,TRUNCATE TABLE始终锁定表和页,而且速度更快

4、表中将毫无例外的不保留任何页,执行DELETE语句后,表仍会包含空页。例如,必须至少一个排他(LCK_M_X)表锁,才能释放堆中的空页。如果执行删除操作时没有使用表锁,表(堆)中将包含许多空页。对于索引、删除操作会留下一些空页,尽管这些页会通过后台清楚迅速释放。

TRUNCATE TABLE删除表中的行的所有行,但表结构以及其列、约束、索引等保持不变。若删除表定义以及其数据,使用Drop table语句。

所以对于像及时的删除数据,然后释放空间,可以采用的方法有:

1、在表格建立聚集索引

2、如果所有数据都不要了,要使用TRUNCATE TABLE而不是delete

Delete 不能完全释放空间,会不会造成空间泄露了呢?其实不用担心,虽然没有将这些页面释放掉,但是当表格插入新的数据的时候,这些页面会被重新使用的。所以这些页面并没有“泄露”掉,会留给SQL Server重用。

如果真的非要用DELETE语句,如果表有聚集索引,重建一下索引能释放掉出这些空间,但是如果没有,可以重建一张新表,把数据从旧表中倒过去,然后删除旧表,释放空间;也可以在这种表上新建聚集索引,这样有点折腾,当然有时候也没必要非要把空间释放出来,可以等着新数据插入时,直接利用就行。

时间: 2024-11-13 14:59:24

《SQL Server企业级平台管理实践》读书笔记——SQL Server中数据文件空间使用与管理的相关文章

《SQL Server企业级平台管理实践》读书笔记——SQL Server如何设置自动增长和自动收缩项

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server如何设置自动增长和自动收缩项 SQL Server允许用户设置数据库初始值和最大值,可以通过自动增长或者自动收缩进行配置.通过这些配置,我们可以防止数据库空间问题而导致的应用程序修改失败或者SQL Server磁盘空间耗尽的事情发生.一般来讲,如果数据库不是很忙,默认的设置为自动增长,这种方式能够满足大部分的需求.但是在大量并发的情况下,申请数据文件和日志文件增长本身是一件非常消耗系统资源和影响性能的工作.所以如果

《SQL Server企业级平台管理实践》读书笔记——SQL Server中收缩数据库不好用的原因

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server中收缩数据库不好用的原因 数据库管理员有时候需要控制文件的大小,可能选择收缩文件,或者把某些数据文件情况以便从数据库里删除. 这时候我们就要使用到DBCC SHRINKFILE命令,此命令的脚本为: DBCC SHRINKFILE ( { file_name | file_id } { [ , EMPTYFILE ] | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATE

《SQL Server企业级平台管理实践》读书笔记——SQL Server数据库文件分配方式

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server数据库文件分配方式 1.文件分配方式以及文件空间检查方法 最常用的检查数据文件和表大小的命令就是:sp_spaceused 此命令有三个缺陷:1.无法直观的看出每个数据文件和日志文件的使用情况.2.这个存储过程依赖SQL Server存储在一些系统视图里的空间使用统计信息计算出的结果,如果没有更新空间统计信息,比如刚刚发生大数据插入,sp_spaceused的结果就不准确.3.这个命令主要是针对普通用户的数据库,对

《SQL Server企业级平台管理实践》读书笔记——几个系统库的备份与恢复

原文:<SQL Server企业级平台管理实践>读书笔记--几个系统库的备份与恢复 master数据库 master作为数据库的主要数据库,记录着SQL Server系统的所有系统级信息,例如登录用户.系统配置设置.端点和凭证以及访问其他数据服务器所需要的信息.master数据库还记录着启动服务器实例所需要的初始化信息,每个其它数据库的主文件位置.master数据库是SQL Server启动的时候打开的第一个数据库.SQL Server是从这个数据库里找到其它数据的信息的.如果master数据

jQuery内核详解与实践读书笔记1:原型技术分解2

上一篇已经搭建了一个非常简陋的jQuery框架雏形,如没有阅读搭建过程,请先阅读<jQuery内核详解与实践读书笔记1:原型技术分解1>初始搭建过程.接下来,完成书中介绍的剩下三个步骤: 7. 延续--功能扩展 jQuery框架是通过extend()函数来扩展功能的,extend()函数的功能实现起来也很简单,它只是吧指定对象的方法复制给jQuery对象或jQuery.prototype对象,如下示例代码就为jQuery类和原型定义了一个扩展功能的函数extend(). 1 var $ = j

程序设计导引及在线实践 读书笔记2.1 —— 鸡兔同笼

http://blog.csdn.net/pipisorry/article/details/36433305 问题描述 一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外).已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物. 输入 第1行是测试数据的组数n,后面跟着n行输入.每组测试数据占1行,每行一个正整数a (a < 32768) 输出 输出包含n行,每行对应一个输入,包含两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用一个空格分开

JavaScript 设计模式与开发实践读书笔记 http://www.open-open.com/lib/view/open1469154727495.html

JavaScript 设计模式与开发实践读书笔记 最近利用碎片时间在 Kindle 上面阅读<JavaScript 设计模式与开发实践读书>这本书,刚开始阅读前两章内容,和大家分享下我觉得可以在项目中用的上的一些笔记. 我的 github 项目会不定时更新,有需要的同学可以移步到我的 github 中去查看源码: https://github.com/lichenbuliren/design-mode-notes 1.currying 函数柯里化 currying 又称 部分求值 .一个 cu

《Spring实战》读书笔记--SpringMVC处理Multipart数据

<Spring实战>读书笔记--SpringMVC处理Multipart数据 1.Multipart介绍 1.1 Multipart形式的数据 Multipart格式数据会将一个表单拆分为多个部分(part),每个部分对应一个输入域.在一般的表单输入域中,它对应的部分会放置文本型数据,如果是文件上传形式,它对应的部分可以是二进制. 1.2 Multipart/form-data请求方式 Multipart/form-data是建立在HTTP的POST请求方式以上的请求,其一般用于HTTP文件上

《SQL Server企业级平台管理实践》读书笔记——SQL Server中关于系统库Tempdb总结

Tempdb系统数据库是一个全局资源.可供连接到SQL Server实例的全部用户使用. 存储的内容项: 1.用户对象 用户对象由用户显示创建.这些对象能够位于用户会话的作用域中.也能够位于创建对象所用例程的作用域中. 例程能够是存储过程.触发器或用户自己定义函数. 用户对象能够是一下项内容之中的一个: 用户定义的表和索引 系统表和索引 全局暂时表和索引 table变量 表值函数中返回的表 2.内部对象 内部对象是依据须要由SQL Server数据库引擎创建的,用户处理SQL Server语句.