数据库索引总结

    求职面试中,经常问到索引相关问题。故此做个总结。

    首先,为什么要用索引?很多人会回答提高查询效率,那么为什么索引能提升查询效率呢?原因是内部数据结构的设计(索引页和B-  B+树)。下面进行一些概念的总结,参考了书本和博客,加入了一些自己的理解。

  1. 数据库基础知识

    数据库是以页为存储单元的,存放数据的叫数据页,放索引的称为索引页。不难理解,无序的存储数据,必然导致查询效率的低下,所以用一种数据结构来组织数据势在必行。

  2. B-树  B+树的概念

  •   B-树

       B-树是一种平衡的多路查找树。

      定义

    一颗m阶的B-树,或为空树,或为满足下列特性的m叉树

  1. 树中每个结点至多有m棵子树;
  2. 若根结点不是叶子结点,则至少有两个子树
  3. 除根之外的所有非终端结点至少有 ⌈m/2⌉棵子树
  4. 每个非终端结点都包含下列信息的数据   
             (n,A0,k1,A1,K2,...,Kn,An)

其中: Ki(i=1...n)为关键字,且Ki<Ki+1(i=1,...,n-1);Ai(i=0,...,n)为指向子树根结点的指针,且指针Ai-1所指子树中所有结点的关键字均小于Ki(i=1,...,n),An所指子树所有结点的的关键字均大于Kn,n(⌈m/2⌉-1<=n<=m-1)为关键字的个数(或n+1为子树个数)


简单理解,非终端结点中,按照上述信息结构,以该结点为根左边的子树的所有结点的关键字,小于它,关键字右边的子树的所有关键字则大于它。例如下图,结点c,关键字43左边子树为39,39<43,右边子树关键字 是 47 53 64 都大于它,关键字78右边子树为99,99>78。

如下图是一颗4阶的B-树

\


  • B+树

    B+树是应文件系统所需而出的一种B-的变形树。一棵m阶的B+树和m阶的B-树的差异在于:

  1. 有n棵子树的结点中含有n个关键字
  2. 所有的叶子结点包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小而自小二大顺序链接
  3. 所有的非终端结点可以看成是索引部分,结点中仅含有其子树(根结点)中的最大(或最小)关键字
    如下图,每个非终端结点的仅含有子树的最大关键字





  3. 堆  聚集索引 非聚集索引 

  •   概念

    是没有聚集索引的表。

    聚集索引按照其作用来下定义,它使得数据行按照聚集索引的键的顺序来排序和存储。每个表只能有一个聚集索引,因为数据行只能按照一个排序顺序进行存储。(tips:  ms sql server在创建 PRIMARY KEY 约束时,如果不存在该表的聚集索引且未指定唯一非聚集索引,则将自动对一列或多列创建唯一聚集索引。 主键列不允许空值。)

   非聚集索引  按我的理解是对聚集索引的一种补充,以除了聚集索引键包含的列为条件来检索数据。在数据行外另外建立数据结构, 非聚集索引包含非聚集索引键值,并且每个键值项都有指向包含该键值的数据行的指针。从非聚集索引中的索引行指向数据行的指针称为行定位器。 行定位器的结构取决于数据页是存储在堆中还是聚集表中。 对于堆,行定位器是指向行的指针。 对于聚集表,行定位器是聚集索引键。(tips:ms sql server 在创建 UNIQUE 约束时,默认情况下将创建唯一非聚集索引,以便强制 UNIQUE 约束。 如果不存在该表的聚集索引,则可以指定唯一聚集索引。

    ps: 每个表只能有一个聚集索引,可以有多个非聚集索引。


  4. 索引优化

  • 包含索引(include)

         通过包含非键列,可以创建覆盖更多查询的非聚集索引。返回具有更多列的结果。本质是返回一个全表的子集,如果返回的列刚好包含的所需要的所有数据,通常称为覆盖查询,显然效率更高。

这是因为非键列具有下列优点:

  • 它们可以是不允许作为索引键列的数据类型。

  • 在计算索引键列数或索引键大小时, 数据库引擎 不考虑它们

  •  筛选索引

        筛选索引是一种经过优化的非聚集索引,尤其适用于涵盖从定义完善的数据子集中选择数据的查询。 筛选索引使用筛选谓词对表中的部分行进行索引。 与全表索引相比,设计良好的筛选索引可以提高查询性能、减少索引维护开销并可降低索引存储开销。其实就是根据需求的一个全表非聚集索引的子集。

具体在ms sql server 使用可以参照官网点击打开链接


   5. 总结

    索引建立是为了提示检索效率,要知其然而且知其所以然,必须要了解索引内部的实现机制。面试问到索引优缺点等也是如此,知道了索引的实现,就知道维护的代价,这就是网上很多索引总结说的。

  •    索引的建立需要额外空间
  •    索引的维护需要时间和空间

        这就涉及B- B+树插入时结点的拆分合并,这里不做讨论。

  • 索引碎片影响数据库性能

    页拆分(是指当页已存满,插入新纪录时会将大约一半的页移到新页再进行插入)、数据库更新、删除操作可能导致碎片的产生。碎片的概念参考点击打开链接