SQL Server索引进阶第十篇:索引的内部结构

  索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就获取到的,很多的技术人员因为不恰当的创建索引,最后使得其效果适得其反,可以说“成也索引,败也索引”。        

    本系列文章来自Stairway to SQL Server Indexes,然后经过我们团队的理解和整理发布在agilesharp,希望对广大的技术朋友在如何使用索引上有所帮助    
    

系列文章索目录:

SQL Server索引进阶第一篇:索引介绍
SQL Server索引进阶第二篇:深入非聚集索引
SQL Server索引进阶第三篇:聚集索引
SQL Server索引进阶第四篇:页和区

SQL Server索引进阶第五篇:索引包含列
SQL Server索引进阶第六篇:书签
SQL Server索引进阶第七篇:过滤的索引

SQL Server索引进阶第八篇:唯一索引
SQL Server索引进阶第九篇:解读执行计划
SQL Server索引进阶第十篇:索引的内部结构
SQL Server索引进阶第十一篇:索引碎片分析与解决(上)
SQL Server索引进阶第十一篇:索引碎片分析与解决(中)-碎片发生原理深度剖析
SQL Server索引进阶第十二篇:索引的创建,修改和删除
SQL Server索引进阶第十三篇:Insert,Update,Delete语句
SQL Server索引进阶第十四篇:索引统计
SQL Server索引进阶第十五篇:索引的最佳实践



    在前一系列文章中我们着重讲述了有关索引各种比较虚的概念,比如索引可以做什么,索引的逻辑结构,接下来是时候来讲述比较实在的东西了,也就是索引的物理结构。理解索引的内部结构对于整体的理解索引是至关重要的,只有理解了索引的内部结构以及SQL Server是如何维护索引的,你才能理解数据插入,删除,更新,索引的创建、修改、删除所带来的成本。

叶子层级和非叶子层级    

    所有的索引都是由叶子层级和非叶子层级组成的。前面的文章主要关注了索引的叶子层级。对于聚集索引来说,叶子节点就是索引本身,每一个叶子节点所包含的条目其实就是表中的行。对于非聚集索引来说,叶子节点每一个叶子包含的一行就是一个条目。每一个条目由索引键列,可选的包含列以及书签构成,而书签又由聚集索引键或RID构成。                无论索引中条目是来自表行(聚集索引叶子节点),指向表行(非聚集索引叶子节点)或是指向低层级的节点(非叶子节点),索引条目都可以被称为索引行。  
     非叶子节点是叶子节点层级的上层,SQL Server使用非叶子节点来:




  •     使得索引按照索引键聚集有序
  •     根据索引键快速找到叶子节点

    在本系列第一篇文章中,我们使用电话本的类比来解释为什么索引能够带来性能的提升。用户知道电话本是按照姓氏进行排序的,因此如果需要找”Meyer, Helen”根据首字母M知道这个人大概在电话本的中间位置,用户直接翻开大约一半电话本开始查找。但对于SQL Server来说,可并不知道什么是按字母表排序,也不知道哪一些页是所谓的中间页,除非把索引中的所有页扫描一遍。为了不用扫描所有的页来找到所需条目,SQL Server为在叶子节点之上增加了额外的页。

非叶子层级  

    这些额外的页也就是所谓的非叶子节点,或被称为索引的节点层级,是建立在叶子层级之上的层级。非叶子层级的作用是使得SQL Server对于特定的索引进行查找时,不仅有了统一的入口页,并且不再需要扫描所有的页。          
     在索引中的所有页,无论哪个层级,都包含索引条目。正如文章中不断重复说的,对于聚集索引来说,叶子节点的条目包含实际的行,所以如果一个表中包含了10亿行,那么叶子节点包含了10亿个条目。    在叶子节点之上的层级,也就是非叶子节点的最底层,非叶子节点的最底层每一个索引条目都指向叶子节点。如果说表中每一页能容纳100个条目,那么刚才的十亿行需要1000000000/100=1000万个页,与之对应的是,那么最底层的非叶子节点就包含了1000万的条目,也就是分布在1000万/100=10万个页中。(译者注:原作者这里没说全,通常来说非叶子节点只包含索引键,因此每个条目的大小会远远小于叶子节点的条目大小,因此每页可以容纳更多的行,所以这里非叶子节点应该远远小于10W个页,后面的段落我们先不管这个,还是按照10W个页算)。  

     再上一层的非叶子节点包含了指向这10万个页的条目,也就是10万个条目,这10W个索引条目分布在10万/1000=1000页中。根据这个规律,我们知道再上一层包含10个页,直至最上层的节点只有一个页了。
  
     索引中最上层的节点被称为根页。剩下的除了根页和叶子之外的层级就是所谓的中间层级。层级的编号是从叶子节点以0开始向上增长的,因此中间层级是以1开始的。    非叶子节点仅仅包含索引键,对于拥有包含列的索引来说,包含列仅仅存在于叶子节点。
    
    索引中的页,除了根页之外,都含有两个额外的指针,分别指向按照索引顺序当前页之前和之后的页。这种双向链表结构使得SQL Server在索引扫描的时候更加有效。

一个简单的例子   

    让我们通过一个简单的图示来真正理解索引的内部结构吧,如下图1所示。我们在Personnel.Employee表上创建了一个非聚集索引,代码如下:

  1.   CREATE NONCLUSTERED INDEX IX_Full_Name ON Personnel.Employee ( LastName, FirstName, ) GO  
复制代码

图例注释:     指向页的指针包含了文件号和页号。比如说5:4567指向的就是第5个文件的4567个页。

1001.jpg(81.01 K)
9/9/2012 11:19:21 AM


图1.索引的竖切图    
    值得说明的是,上面的图只是一个样子,正常的情况下一个页中会包含远多于上面例子的行,并且页也会远远多于上面的例子。    
    实际在页中索引条目并不是有序的,而是靠偏移指针进行定位的,这个页尾的偏移表是有序的。    
    很多情况下,页中并不像上面图中所展现的那样,页之间物理上是连续的,但它们之间逻辑上是连续的,逻辑和物理上的差异被称之为碎片。  
     正如我们之前所说,每一个索引可以包含不止一层的中间页。    
    继续使用我们之前电话本的类比。比如你查找名为Helen Meyer的联系人,打开电话本找到第一页,对于在区间 “Fernandez, Zelda”和 “Olsen, Karl”之间的名字,去看页5:431.然后你找到431页,这页告诉你对于Kumar, Kevin”和“Nara, Alison”之间的名字,去找页5:2006。然后你找到5:2006就找到了你所需的联系人。

索引深度    

    索引的根页以及相关信息是存在系统表中的。每当SQL Server进行页查找时,SQL Server都会从根页开始查找,经过中间节点,直到找到叶子节点,然后从叶子中找到需要的索引条目。对于我们10亿行的表来说,从根节点到叶子节点共需要读取5层。而对图1所示的节点来说,只需要读取3次IO。    
    上面所说的层数,也被成为索引深度。取决于索引键的大小和数量。在AdventureWorks示例数据库中,没有哪个索引的层级超过3层。但对于其它索引键宽或是数据量大的表,就会有更深的层级。    sys.dm_db_index_physical_stats函数可以展示索引的详细信息,深度和大小。这是一个表值函数,比如下面代码我们可以找到SalesOrderDetai表相关的索引信息

  1. SELECT  OBJECT_NAME(P.OBJECT_ID) AS 'Table' ,
  2.         I.name AS 'Index' ,
  3.         P.index_id AS 'IndexID' ,
  4.         P.index_type_desc ,
  5.         P.index_depth ,
  6.         P.page_count
  7. FROM    sys.dm_db_index_physical_stats(DB_ID(),
  8.                                        OBJECT_ID('Sales.SalesOrderDetail'),
  9.                                        NULL, NULL, NULL) P
  10.         JOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID
  11.                               AND I.index_id = P.index_id ;
复制代码

得到的结果如图2所示。

index1002.jpg(29.54 K)
9/9/2012 11:19:21 AM


图2.查询sys.dm_db_index_physical_stats函数得到的结果
    
    通过如下代码我们可以看到更详细的层级信息.SELECT  OBJECT_NAME(P.OBJECT_ID) AS 'Table' ,

  1.         I.name AS 'Index' ,
  2.         P.index_id AS 'IndexID' ,
  3.         P.index_type_desc ,
  4.         P.index_level ,
  5.         P.page_count
  6. FROM    sys.dm_db_index_physical_stats(DB_ID(),
  7.                                        OBJECT_ID('Sales.SalesOrderDetail'), 2,
  8.                                        NULL, 'DETAILED') P
  9.         JOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID
  10.                               AND I.index_id = P.index_id ;
复制代码

得到的结果如图3所示。

1003.jpg(23.53 K)
9/9/2012 11:19:21 AM


图3.查询索引的详细信息通过图3所示结果,可以看出




  •     叶子节点的条目分布在407页中
  •     中间节点仅仅需要2页
  •     根节点只有1页

    根据索引键的选择,书签的大小的不同,叶子节点通常是非叶子节点大小的上百倍。根据具体的数据不同而不同。    
    记住包含列仅仅适用在非聚集索引并且只存在于叶子节点中,包含列对于上层的层级是透明的,这也是为什么包含列不会增加非叶子节点键的大小。    
    因为聚集索引的叶子节点是表数据本身,所以除了叶子节点的数据是表数据本身之外,还需要存储一些额外的非叶子层级。因为无论是否有聚集索引数据本身都是存在的,所以创建聚集索引的时候不仅需要花费一些时间和资源,创建成功后还需要一些额外的空间存储非叶子节点。

总结    

    索引的结构使得SQL Server可以根据键值快速找到所需的列,一旦找到所需的列之后,SQL Server可以:


  •     直接访问所需的行
  •     从找到的数据位置开始,根据双向链表找相邻的页

    索引树结构早已经在没有关系数据库时就开始被使用了,事实证明,这是一种优秀的结构。

 

转载于:https://www.cnblogs.com/lteal/archive/2012/12/03/2799321.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDK安装及java环境配置_JDK安装及Java环境变量配置

2.点击Accept License Agreement,下载适合自己电脑版本的JDK.由于我的电脑是windows10 64位专业版。点击红色下载按钮。保存位置自己决定,只要自己安装时能找到就行。3.找到安装文件,双击。4.下一步,这里会让你选择安装目录。注意…

使用 NuGet 管理项目库

共享和重用代码是一个很大的挑战。 不相信? 请随便走进一间中型或大型工作室,问问他们有多少日志记录库。 访问多家公司后,您将发现他们拥有比例非常高的内部日志记录库,而这些库中有一些非常不错,例如,Log…

33张你没看过的酷炫化学动图, 秒懂化学反应原理!

化学的神奇魅力可是不是随便说说的,神奇起来让人叹为观止。下面就让腾远君带领大家看看传说中的37张神图,了解化学之美吧。1 . 硫氰酸汞分解(“法老之蛇”)原理:硫氰酸汞受热分解,部分产物燃烧。2Hg(SCN)2→…

二分 + 模拟 - Carries

Carries Problems Link Mean: 给你n个数,让你计算这n个数两两组合相加的和进位的次数. analyse: 脑洞题. 首先要知道:对于两个数的第k位相加会进位的条件是:a%(10^k)b%(10^k)>10^k. 想到这一点后就简单了,枚举每一位&#…

Mvc3(1)

摘录于Pro ASP.NET MVC3 Framework一书: 一. Web Form的缺点 1. view state weight: view state 中保存的数据在每次HTTP请求中来回传递,且包含的数据量可以达到很大,导致用户响应时间比较慢,增加了带宽要求 2.页的生命周期相当…

从编译器层面理解C#中的闭包的这个坑!

前言在公众号上看到一篇文章《正确使用和理解C#中的闭包》,里面提到了闭包的一个坑:当捕获的外部变量为for循环的迭代变量时,C#认为变量i是定义在循环体外的。所以,当添加委托集合的for循环执行完时,i的值已经变为3了&…

ssh 与 locale

1 我的 ubuntu 11.10 使用 zh_CN.UTF-8 ,导致连接到 ssh 服务器上显示中文,本来是很方便的,但是最近要监控某些功能,需要ssh 服务器(en_US.UTF-8)显示英文 ! locale LANGzh_CN.UTF-8 LANGUAGEzh_CN:en_US:…

C# 使用 HelpProvider 控件调用帮助文件

HelpProvider控件可以将帮助文件(.htm文件或.chm文件)与 Windows 应用程序相关联,为特定对话框或对话框中的特定控件提供区分上下文的帮助,打开帮助文件到特定部分。如目录、索引或搜索功能的主页。如图1 所示为 HelpProvider 控件。图1 HelpProvider…

哈哈哈,弟弟被卡桶里了......

1 哈哈哈哈哈弟弟被卡桶里面了(via.小妮)(注意安全,请勿模仿!)▼2 弟弟是个狠人▼3 Self-potato: 一种不需要沙发也能无意义地待着的生活方式(via.字幕少女)▼4 防晒的正确打开方…

LVM基本应用 扩展及缩减实现

LVM: Logical Volume Manage首先;pv管理工具: pvs:简要pv信息显示 pvdisplay:显示pv的详细信息pvcreate /dev/DEVICE: 创建pvvg管理工具: vgs vgdisplayvgcreate [-s #[kKmMgGtTpPeE]] VolumeGroupName Physical…

java 线程 插件_我的第一个Chrome插件:天气预报应用

1.Chrome插件开发基础开发Chrome插件很简单,只要会基本的前台技术HTML、CSS、JS就可以开发了。Chrome插件一般包括两个HTML页面background和popup。background页面只在启动浏览器加载插件时载入一次,它不直接显示出来而是在后台运行。它包含了插件的主要…

mysql 时区设置

找到my.cnf或者my.ini [mysqld] default-time-zone8:00 转载于:https://www.cnblogs.com/lost-1987/articles/2799639.html

SQLite移植手记1

SQLite实现了大部分SQL92标准的SQL语句,同时支持ACID。还有其它许多特性这里不做深究,因为这在嵌入式领域来说应该是够用了。 下载:下载页面:http://www.sqlite.org/download.html我使用的还是当前最新版本:sqlite-3.3…

Dapr牵手.NET学习笔记:Actor一个场景

接上一篇最后的场景,为了解决相同帐户并发引起的数据库行级锁,可以引入Actor的串机制,相同ActorID的实例,串行,这样就能在应用层把读取余额的资源争抢解决掉,剩下的工作就是一定时间间隔,把内存…

【python】抄写大神的百度贴吧代码

原文链接:http://cuiqingcai.com/993.html 划重点: 1.提取帖子内容时,对图片,贴吧自动增加的超链接,制表符,换行符要做删除或替换处理 2.decode是把bytes转换为str, encode是把str转换为bytes 原帖中的代码…

敏捷开发组织【北京及其他地区QQ群】【长三角QQ群】【珠三角QQ群】

【北京及其他地区QQ群】http://qun.qq.com/#jointhegroup/gid/95849986 上限500人,创建日期2011-03-20,当前人数393,多数来自CSDN,包括北京约100人,长三角100人,珠三角100人,其他地区100人。未来…

保送北大,连发三篇Science,这位80后川妹子近日再发重磅级研究成果!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自募格学术2020年9月21日,启函生物杨璐菡博士等在 Nature 子刊 Nature Biomedical Engineering杂志上发表了题为:Extensive germline genome engineering in pigs 的研究论文。杨璐菡杨璐菡带领的研究团队成…

TCP/IP 协议简单分析(建立连接握手过程)

原文:http://hi.baidu.com/wuguoyana/blog/item/38c04d3bcf047ce43a87ce55.html 首先TCP和IP是两种不同的协议,它们来七层网络模型中分别在不同的层次,IP协议是网络层的协议,TCP是更高一层的传输层的协议,TCP是建立在I…

java 继承接口语法_java的继承、接口方面的语法及知识

}父类的属性子类中都存在,只是有没有权限访问的问题根据名字找谁是谁?1.变量-> 类型 (类、接口)->接口2.已经确定是变量局部变量、形参->类的属性-> 外部类的属性就近原则构造方法:注意默认的那个无参构造方法优先调用父类的构造…

Linq 下的 Take() 方法内部机制是怎样的?

咨询区 Rahul Kishore:我的web需要访问数据库,但是表比较大,我仅仅想要获取该表中 N 条数据,我查阅了 MSDN 文档,看到了一个 Take() 方法,我现在很疑惑它的运行机制是下面哪一种?先从数据库中获…