SQL Server中的索引内部结构:到SQL Server索引级别10的阶梯。
大卫•杜兰特2012/01/20
该系列
本文是楼梯系列的一部分:SQL Server索引的阶梯。
索引是数据库设计的基础,并且告诉开发人员使用数据库对设计人员的意图有很大的影响。不幸的是,当性能问题出现时,索引常常被添加为事后考虑。这里最后是一个简单的系列文章,应该让任何数据库专业人员迅速“跟上”他们。
在以前的水平上,我们对索引采取了一种合乎逻辑的方法,专注于他们能为我们做什么。现在是时候采取物理方法,检查指标的内部结构了;为了理解索引内部,可以理解索引开销。只有了解索引结构,以及如何维护它,才能理解和最小化索引创建、更改和删除的成本;以及行插入、更新和删除。
因此,从这个层次开始,我们将重点扩展到包括索引的成本,以及索引的好处。毕竟,将成本最小化是利益最大化的一部分;最大化你的索引的好处就是这个楼梯的目的。
叶和叶水平
任何指标的结构都是由叶级和非叶级组成。虽然我们从未明确地说过,所有以前的水平都集中在一个指数的叶级上。因此,它是一个聚集索引的叶级,即表本身;每个叶级条目都是表的一行。对于非聚集索引,它是每一行包含一个条目的叶级(过滤后的索引除外);每个条目由索引键列组成,可选的包含列和书签,它要么是聚集索引键列,要么是RID(行ID)值。
索引项也称为索引行;无论它是表行(聚集索引叶级别条目),都是指表行(非聚集索引页级),或指向较低级别的页面(非叶级)。
非叶级是构建在叶级之上的结构,它使SQL Server能够:
在索引键序列中维护索引的条目。
快速查找给定索引键值的叶级行。
在第1级,我们使用电话簿作为类比来解释索引的好处。我们的电话簿用户,正在寻找“迈耶,海伦”,知道条目将会在任何排序的姓氏列表中间,然后直接跳到中间的白色页面开始搜索。然而,SQL Server并没有这样的内部知识,即英语的姓氏或其他任何数据。它也不知道哪个页面是“中间”页面,除非它从头到尾遍历整个索引。因此,SQL Server为索引构建了一些额外的结构。

非叶水平
这种附加结构称为索引的非叶级或节点级别;它被认为是建立在叶层之上,不管它的页面在哪里。它的目的是为SQL Server提供每个索引的单个页面入口点,以及从该页面到包含任何给定搜索键值的页面的短遍历。
索引中的每个页面,无论其级别如何,都包含索引行或条目。在页级页面中,正如我们反复看到的,每个条目都指向一个表行或者是表行。因此,如果表包含10亿行,索引的叶级别将包含10亿个条目。
在叶级以上的水平,即最低的非叶层;每个条目指向一个叶级页面。如果我们的10亿条目索引平均每个页面100个条目,对于一个索引的搜索键包含几个数字、日期和代码列,这是一个现实的数字;然后,叶级将包含1000,000,000 / 100 = 10,000,000页。反过来,最低的非叶级将包含10,000,000个条目,每个条目指向一个叶级页面,并且将跨越100,000页。
每一个较高的非叶级别都有页面,每个页面的条目都指向下一级的页面。因此,我们的下一个更高的非叶级别将包含100,000个条目,并有1000页大小。上面的级别包含1000个条目,大小为10页;上面的那一页只有一页上的10个条目;这就是它停止的地方。
位于索引顶部的唯一页面称为根页面。在根页级和叶级以上的索引的级别称为中间层。等级的编号从零开始,从叶级开始向上。因此,最低的中级水平总是1级。
非叶级条目只包含索引键列和指向较低级页面的指针。包含的列只存在于叶级条目中;它们不在非叶级条目中进行。
除了根页面之外,索引中的每个页面都包含两个额外的指针。这些指针指向下一页和前一页,在索引序列中,在同一级别上。由此产生的双向页面链使SQL Server能够以升序或降序的顺序扫描任何级别的页面。
一个简单的例子
下面的图1所示的简单图帮助说明了这种树状结构的索引。此图表示在理论人员的LastName / FirstName列上创建的索引。Employee表,使用以下SQL:

CREATE NONCLUSTERED INDEX IX_Full_Name
ON Personnel.Employee
(
LastName,
FirstName,
)
GO

图注:
指向页面的指针包括数据库文件号和页码。因此,指针值为5:4567指向数据库文件#5的4567页。
大多数样本值都是从这个人那里取来的。在AdventureWorksdatabase中的联系人表。为了说明目的,还添加了一些其他的内容。
卡尔·奥尔森是样本中最受欢迎的名字。有这么多卡尔·奥尔森,他们的条目跨越了整个中间水平的索引页。

图1 -索引的垂直切片。
为了清晰和说明,图表不同于一个典型的指数:
一个典型索引中的每个页面的条目数将大于图中所示的数字,因此,除了根之外,每个级别的页面数都大于显示的页数。叶级,特别是,将有远多于可以显示在我们的空间有限图。
实际索引的条目没有在页面上进行排序。这是页面的条目偏移指针,它提供对条目的排序访问。(请参阅第4级-页面和扩展,以获得关于偏移指针的更多信息。)
通常情况下,索引的物理和逻辑序列之间的相关性比图表中显示的要多。该索引的物理和逻辑序列之间缺乏相关性称为外部碎片,并在第11层中讨论。
如前所述,索引可以有多个中间级别。
就好像我们的白页用户在寻找海伦·迈耶,打开电话簿,发现第一页,也只有第一页,是粉红色的。在“粉红页”的排序条目列表中,有一个人说:“在费尔南德斯、塞尔达和奥尔森之间的名字”,卡尔“见蓝页5:431”。当我们的用户浏览到blue page 5:431时,页面上的一个条目写道:“在库玛尔、凯文”和“奈良”之间的名字,参见“白色页5:2006”。粉色的页面对应的是根,蓝色的页面是中间的,白色的页面是叶子。
指数深度
根页面的位置存储在系统表中,以及其他关于索引的信息。每当SQL Server需要访问与索引键值相匹配的索引项时,它就从根页面开始,并在索引中每一级的一个页面上工作,直到到达包含该索引键的条目的叶级页面为止。在我们的10亿行表示例中,5页的读取将把SQL Server从根页面带到叶级页面及其所需的条目;在我们的图表示例中,三个读取就足够了。在聚集索引中,这个叶级别条目将是实际的数据行;在非聚集索引中,该条目将包含聚集索引键列或RID值。
索引的级别或深度的数量取决于索引键的大小和条目的数量。在AdventureWorks数据库中,没有索引的深度大于3。在具有非常大的表或非常宽的索引键列的数据库中,可能会出现6个或更大的深度。
sys。dm_db_index_physical_statsfunction提供了索引类型、深度和大小等索引的信息。它是一个可查询的表值函数。清单1中的示例返回SalesOrderDetailtable的所有索引的汇总信息。

SELECT OBJECT_NAME(P.OBJECT_ID) AS 'Table', I.name AS 'Index', P.index_id AS 'IndexID', P.index_type_desc , P.index_depth , P.page_count FROM sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID('Sales.SalesOrderDetail'), NULL, NULL, NULL) PJOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID AND I.index_id = P.index_id;清单1:查询sys。dm_db_index_physical_stats函数,如图2所示。

图2:查询系统的结果。dm_db_index_physical_stats函数
相反,清单2中所示的代码请求特定索引的详细信息,这是表中SalesOrderDetail表的惟一标识符列的非聚集索引。它返回每个索引级别的一行,如图3所示。
清单2:查询系统。dm_db_index_physical_stats详细信息。

SELECT OBJECT_NAME(P.OBJECT_ID) AS 'Table', I.name AS 'Index', P.index_id AS 'IndexID', P.index_type_desc , P.index_level  , P.page_count FROM sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID('Sales.SalesOrderDetail'), 2, NULL, 'DETAILED') PJOIN sys.indexes I ON I.OBJECT_ID = P.OBJECT_ID AND I.index_id = P.index_id; 

图3:查询系统的结果。dm_db_index_physical_stats为详细信息

从图3所示的结果中,我们可以看到:
该指数的叶级分布在407页。
唯一的中级水平只需要两页。
根级别始终是一个页面。
索引的非叶部分的大小通常是叶级的十分之一到百分之一。根据哪些列组成了搜索键、书签的大小,以及是否指定了包含的列。换句话说,相对而言,索引是非常宽且非常短的。这与大多数的索引示例图不同,如图1中所示,它通常是高而窄的。
记住,包含的列只适用于非聚集索引,它们只出现在叶级条目中;它们从较高级别的条目中删除,这就是为什么它们不添加到非叶级别的大小。
由于聚集索引的叶级别是表的数据行,所以只有聚集索引的非叶部分是附加信息,需要额外的存储。数据行将存在是否创建索引。因此,创建聚集索引可能需要时间和消耗资源;但是当创建完成时,数据库中消耗的额外空间很少。
结论
索引结构使SQL Server能够快速访问特定索引键值的任何条目。一旦找到该条目,SQL Server可以:
访问该条目的行。
从这一点通过升序或降序遍历索引。
这种索引树结构已经使用了很长时间,甚至比关系数据库还要长,而且随着时间的推移已经证明了它自己。

转载于:https://www.cnblogs.com/yyyz516/p/8257247.html

翻译:SQL Server中的索引内部结构:到SQL Server索引级别10的阶梯。相关推荐

  1. SQL SERVER中什么情况会导致索引查找变成索引扫描

    原文:SQL SERVER中什么情况会导致索引查找变成索引扫描 SQL Server 中什么情况会导致其执行计划从索引查找(Index Seek)变成索引扫描(Index Scan)呢? 下面从几个方 ...

  2. sql游标 while_用SQL Server中的排名函数替换SQL While循环和游标,以提高查询性能

    sql游标 while SQL While loop and cursor are the most common approach to repeat a statement on conditio ...

  3. 服务器中勒索病毒解密恢复 SQL数据库中勒索病毒解密恢复 SQL数据库被加密恢复...

    服务器中勒索病毒解密恢复 SQL数据库中勒索病毒解密恢复 SQL数据库被加密恢复 前天接到一位客户求救 说几台服务器都中招了,这个也很常见了.客户发来加密的MDF后,我们使用数据库修复软件 任何一款 ...

  4. SQL Server中的联合主键、聚集索引、非聚集索引、mysql 联合索引

    我们都知道在一个表中当需要2列以上才能确定记录的唯一性的时候,就需要用到联合主键,当建立联合主键以后,在查询数据的时候性能就会有很大的提升,不过并不是对联合主键的任何列单独查询的时候性能都会提升,但我 ...

  5. percent sql_使用SQL Server中的PERCENT_RANK函数计算SQL百分位数

    percent sql This article explores the SQL Server PERCENT_RANK analytical function to calculate SQL P ...

  6. oracle 12c pl/sql语言,ORACLE 12C SQL语句中通过with 定义PL/SQL 函数

    在ORACLE 12C支持在sql语句中编写函数,用来实现sql语句操作需要使用函数的部分功能,该功能对于你不想在数据库中新建函数 or 你的库是read only模式下要使用新函数实现某种功能,可以 ...

  7. java string转sql date_Java中的util.Date,sql.Date,sql.Time,String类型转换

    今天总结一下工具类中Date类型. java.sql.Date,java.sql.Time,和java.sql.Timestamp(时间戳记)都是java.util.Date的子类. java.sql ...

  8. SQL Server 中的执行计划和SQL Server Profiler

    显示估计的执行计划 包括实际的执行计划 包括客户端统计信息 SQL Server Profiler

  9. SQL SERVER中查询无主键的SQL

    --生成表 IF  EXISTS ( SELECT  name                 FROM    sysobjects                 WHERE   xtype = ' ...

最新文章

  1. Android 动画的插值器 (Interpolator属性)
  2. 注册页面所涉及的知识
  3. 设计中最常用的CSS选择器
  4. c编程:输入一个数字n,则n代表n行,每行输入2个数字a,b计算每行的a+b问题。
  5. 雨棚板弹性法计算简图_钢结构工程量计算、报价要点
  6. python中的max_row_Openpyxl max_row和max_column错误地报告了一个较大的figu
  7. win7台式电脑怎么连wifi_台式电脑怎么用wifi网络
  8. 手把手教你用.NET Core写爬虫
  9. edge浏览器识别ip地址为手机号的解决办法
  10. Atitit 切入一个领域的方法总结 attilax这里,机器学习为例子
  11. iOS底层探索之多线程(十三)—锁的种类你知多少?
  12. 自编基于jQuery实现分页插件
  13. Windows Server 2003 安装教程
  14. rs232接口_USB转RS232接口9针串口线,工控数据转接线驱动安装方法
  15. 51单片机驱动LCD12864中文字库显示
  16. 什么是 GC,有什么作用?
  17. 传统图片超分算法——双三次插值 (Bicubic)、附C++源码
  18. 有了这25个正则表达式,代码效率提高80%
  19. PINN解偏微分方程实例3(Allen-Cahn方程)
  20. 计算机控制实验比例环节,陈sir-实验一 典型环节的电路模拟

热门文章

  1. 为什么孙悟空能大闹天宫,却打不过路上的妖怪?
  2. ORA-27041: unable to open file--恢复被rm意外删除数据文件
  3. windows 7 睡眠和休眠的区别
  4. 2012-04-26 16:08 Director installer fails with error Unable to run run-cds-tool script“
  5. oracle对大对象类型操作:blob,clob,nclob,bfile
  6. Netty事件传播机制
  7. NOIP 2013 day1
  8. golang的缓存io简单的使用
  9. [转载] 新兵训练营系列课程——海量数据存储基础
  10. 绍兴市一男子醉酒驾车还冲上公交车暴打司机