Nuss 阅读(9) 评论(0)

索引(Index),相信大家都知道就是给表中的数据添加了一个目录,使我们可以快速检索到我们想要的数据,但这个目录是什么?SqlServer又是如何管理的?要搞明白这些,我们就要先了解sqlserver数据库中的页(Page),区(Extents)的概念,如有不对的地方,欢迎拍砖指正。

页(Page)

  1. 页是数据存储的最本单位,SqlServer读写也是以页为单位进行的,即页是对数据管理的最小单位。页的大小8192B=8KB, 1MB存储128个数据页。
  2. 一个页具体如下图所示(图片引用MSDN),包含3部分:
    • 头信息Page Hearder,占用96byte,存储关于页的信息,页码,页类型等;
    • 数据行DataRows,具体存储的内容,占用8060byte;
    • 行偏移表Row Offset Table,记录每个数据行第一个字节和页首(即96byte)的距离,顺序和页中行的顺序相反,占36byte;
      图片引自MSDN
  3. 页的类型本文涉及到的主要如下,其它页类型可自行查询MSDN

    • Data:当行中的文本设置为 ON 时,具有除 text、ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据以外的所有数据的数据行。
    • Index:索引条目。
    • Text/Image:大型对象数据类型:(text、ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据),数据行超过 8 KB 时为可变长度数据类型列:(varchar、nvarchar、varbinary 和 sql_variant)

    看到上面的Index页类型,我们就明白了索引和数据行一样也是存储在页中的,而且SqlServer针对不同的数据类型划分了不同的页类型,大数据类型(text,image,varchar(max),nvarchar(max))是存储在Text/Image页类型中的,该类型中还会存储单个数据行超过8KB时的可变长类型,即一页中只有一行,且数据行所占空间大小大于8060(即8192-96-36)byte,实际表中所有列的和不能大于8053byte(两者为啥相差7byte可参考此链接),这种情况下sqlServer会从最大长度的可变长度列开始动态将一个或多个列移动到 ROW_OVERFLOW_DATA 分配单元中的页,并在原始页中维护一个指针,如果后续数据行变小,SqlServer会将列再移回来。

区(Extents)

区是磁盘上连续的8个页,8*8KB=64KB。

  • 混合盘区 Mixed Extents:每个页可能对应不同对象;
  • 统一盘区 Uniform Extents:一个区中的8个页对应一个对象

索引(Index)

通过上面我们已经知道,索引也是存储在页上的,具有聚集索引(Clustered Index)的表是以B-tree(不是B减树。。。)结构组织的且数据按聚集索引顺序存储,否则存储在堆(Heap)上。B树上每一页称为一个索引节点,其中包含:

  • 根节点:顶端节点,包含存有索引行的索引页;
  • 中间级:根和叶节点之间的,同根节点包含存有索引行的索引页;
  • 叶节点:底层节点,包含基础表的数据页;

    索引行:包含一个键值和一个指针,该指针指向B树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被链接在双向链接列表中.

非聚集索引(Nonclustered Index):具有和聚集索引相同的B树,区别如下:

  • 数据行不会按照非聚集键排序和存储;
  • 叶级节点指向的不是数据页而是索引页;

    索引行:包含非聚集键和行定位符,此定位符指向聚集索引或堆中包含该键值的数据行.

表组织结构图(图片引用MSDN),最底下一行是三种分配单元,详细可直接前往MSDN连接查看。

一些思考:

通过以上内容,我们可以更直观,更容易总结出:

  1. 应该尽量把索引设置在较窄的列上,这样一个页上就可以存储更多的索引行,检索的效率就高了;
  2. 经常变动的列上不宜设置索引,因为会导致数据行及索引页的一连串修改调整;
  3. 建立多个索引可以提供表的查询性能,但同时也增加了修改数据的复杂度;
  4. 索引应尽量覆盖查询,因为数据全部存储在索引中,从而减少了磁盘I/O
    ...

最近花了一些时间整理了一下页,区,索引的相关知识点,并看了一些博客,感觉之前很多不懂的地方都豁然开朗了,其实相关内容还有很多 ,这里只是介绍了一部分,另外我们还是要多看官方文档(MSDN建议看英文的,中文翻译的好多地方让你很迷惑,看英文版反而能看懂)和大牛们的博客。

参考链接

  1. MSDN : https://docs.microsoft.com/zh-cn/sql/relational-databases/pages-and-extents-architecture-guide
  2. http://www.cnblogs.com/woodytu/p/4486193.html