聚簇索引和非聚簇索引原理

  聚集索引与非聚集索引的区别是:叶节点是否存放一整行记录

  InnoDB 主键使用的是聚簇索引,MyISAM 不管是主键索引,还是二级索引使用的都是非聚簇索引。

  

 

 

   对于非聚簇索引表来说(右图),表数据和索引是分成两部分存储的,主键索引和二级索引存储上没有任何区别。使用的是B+树作为索引的存储结构,所有的节点都是索引,叶子节点存储的是索引+索引对应的记录的数据。

  对于聚簇索引表来说(左图),表数据是和主键一起存储的,主键索引的叶结点存储行数据(包含了主键值),二级索引的叶结点存储行的主键值。使用的是B+树作为索引的存储结构,非叶子节点都是索引关键字,但非叶子节点中的关键字中不存储对应记录的具体内容或内容地址。叶子节点上的数据是主键与具体记录(数据内容)。

  优点
  1、当需要取出一定范围内的数据时,用聚簇索引比非聚簇索引好。
  2、当通过聚簇索引查找目标数据时理论上比非聚簇索引要快,因为非聚簇索引定位到对应主键时还要多一次目标记录寻址,即多一次I/O。
  3、使用覆盖索引扫描的查询可以直接使用页节点中的主键值。
  缺点
  1、插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,一般都会定义一个自增的ID列为主键。
       2、更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,一般定义主键为不可更新。
       3、二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
          二级索引的叶节点存储的是主键值,而不是行指针(非聚簇索引存储的是指针或者说是地址),这是为了减少当出现行移动或数据页分裂时二级索引的维护工作,但会让二级索引占用更多的空间。
       4、采用聚簇索引插入新值比采用非聚簇索引插入新值的速度要慢很多,因为插入要保证主键不能重复,判断主键不能重复,采用的方式在不同的索引下面会有很大的性能差距,聚簇索引遍历所有的叶子节点,非聚簇索引也判断所有的叶子节点,但是聚簇索引的叶子节点除了带有主键还有记录值,记录的大小往往比主键要大的多。这样就会导致聚簇索引在判定新记录携带的主键是否重复时进行昂贵的I/O代价。

页和操作系统的关系

①为什么要有内存管理?
  一个进程完成功能,需要访问磁盘加载数据到内存,然后等待进入cpu运算,因为数据量大小远远大于内存大小。因此提出虚拟内存概念。虚拟内存就是将程序用到的数据进行划分,暂时用不到的放到磁盘里,用到的放到内存里,操作系统中总是运行着不止一个进程,各个进程有优先级顺序,所以存在进程调度问题,进程的每次调度都会导致内存和磁盘数据置换,段式内存管理页式内存管理都是基于虚拟内存概念的具体内存管理解决方案。
②什么是页式内存管理?

  虚拟内存位于程序和物理内存之间,程序只能看见虚拟内存,不能直接访问物理内存。每个程序都有自己独立的进程地址空间,就做到了进程隔离。进程地址空间是指虚拟地址。在程序和物理地址空间之间增加了虚拟地址,那么就要解决怎么从虚拟地址映射到物理地址,因为程序最终肯定是运行在物理内存中的,主要有分段和分页两种技术。

  分页机制就是把内存地址空间分为若干个很小的固定大小的页,每一页的大小由内存决定,就像Linux中ext文件系统将磁盘分成若干个Block一样,这样做是分别是为了提高内存和磁盘的利用率。

③页的大小为什么是4K?

  CPU位数准确地说应该是CPU一次能够并行处理的数据宽度,一般就是指数据总线宽度。

mysql索引和页的关系
  
  索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。
  为了达到这个目的,磁盘按需读取,要求每次都会预读的长度一般为页的整数倍。而且数据库系统将一个节点的大小设为等于一个页,每个节点只需要一次I/O就可以完全载入。每次新建节点时,直接申请一个页的空间,就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现一个node只需一次I/O。并把B-tree中的m值设的非常大,就会让树的高度降低,有利于一次完全载入。

  MyISAM的是非聚簇索引,B+Tree的叶子节点上的data,并不是数据本身,而是数据存放的地址。主索引和辅助索引没啥区别,只是主索引中的key一定得是唯一的。这里的索引都是非聚簇索引。非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。

        InnoDB的数据文件本身就是索引文件,B+Tree的叶子节点上的data就是数据本身,key为主键,这是聚簇索引。聚簇索引,叶子节点上的data是主键(所以聚簇索引的key,不能过长)。

  InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。

  

 

   

②聚簇索引

  聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。聚簇索引要比非聚簇索引查询效率高很多。
  聚集索引这种主+辅索引的好处是,当发生数据行移动或者页分裂时,辅助索引树不需要更新,因为辅助索引树存储的是主索引的主键关键字,而不是数据具体的物理地址。
非聚簇索引
  非聚集索引,类似于图书的附录,那个专业术语出现在哪个章节,这些专业术语是有顺序的,但是出现的位置是没有顺序的。每个表只能有一个聚簇索引,因为一个表中的记录只能以一种物理顺序存放。但是,一个表可以有不止一个非聚簇索引。

Page结构
  Page是整个InnoDB存储的最基本构件,InnoDB磁盘管理的最小单位,与数据库相关的所有内容都存储在这种Page结构里。Page分为几种类型,常见的页类型有数据页(B-tree Node)Undo页(Undo Log Page)系统页(System Page) 事务数据页(Transaction System Page)等。单个Page的大小是16K(编译宏UNIV_PAGE_SIZE控制),每个Page使用一个32位的int值来唯一标识,对应InnoDB最大64TB的存储容量(16Kib * 2^32 = 64Tib)。

  

   

 

 


  

  

 

  
  

  

posted on 2019-11-11 22:25  溪水静幽  阅读(611)  评论(0)    收藏  举报