数据库索引创建与优化

       对于数据库优化主要包括三个部分:查询优化索引优化和字段类型优化,其中,索引优化则是数据库优化的重中之重。一个查询使用索引与不使用索引的差别可能只在100个数量级,而一个好的索引与不好的索引差别可能在1000个数量级,但是一个最优的索引与普通的索引查询效率可能就相差上万甚至更高的数量级。本文首先会介绍索引的存储结构,然后介绍单表查询使用的单列索引、联合索引、前缀索引等结构,最后会介绍一些困难谓词及不恰当的索引用法。

1. 索引结构

       索引典型的结构是B+树,B+树是平衡树的一种,但是和典型的平衡树不同的是B+树叶子节点上存储了多个元素,并且非叶子节点是由多个元素进行组织的。另外,B+树相对于B树的主要区别在于B+树的叶子节点上存在一个指向下一个叶子节点的指针,这样就便于对叶子节点的数据进行遍历。如下图所示是一个B+树的结构示意图(关于B+树的详细介绍请大家参阅相关的文档):

B+树结构.png

1.1 聚簇索引

       在数据库中,索引主要以两种形式存在:聚簇索引和二级索引。对于二者的区别,可以这么理解,数据库的数据是存储在磁盘上的,那么磁盘上的数据存储肯定是有一定的顺序的,这里聚簇索引就是指组织磁盘数据顺序的索引。对于数据库而言,其是可以存在多个索引的,而磁盘上的数据顺序只可能有一种,因而对于索引而言,一个表只可能有一个索引被定义为聚簇索引(默认是主键索引),其余的索引都属于二级索引。如下图所示为一个聚簇索引组织数据的示意图:

       图中上部分的方框包含的部分就是聚簇索引,下部分方框中的部分表示磁盘数据。可以看到,聚簇索引的结构就是一棵B+树,B+树中每个节点中都包含有顺序组织的数据id,并且每个节点中都留有一部分余量,用来存放新插入的数据。这里主要需要注意的是,在聚簇索引的叶节点上不仅存储了当前数据的id,还存储了该id所指代的数据在磁盘中的地址,并且磁盘上数据的存储顺序与聚簇索引的叶节点的顺序是一致的。这里其实就可以看出来,在通过id查询时,数据库是先根据id定位到聚簇索引的叶节点,然后根据叶节点上数据的地址值获取磁盘上的数据的,由于索引一般存储在内存中,因而定位叶节点数据的消耗可以忽略不计。

       这里需要说明的是,对于聚簇索引具体选择哪个索引作为聚簇索引是有一定规则的,具体的规则如下:

如果当前表存在主键,那么MySQL就会将主键作为聚簇索引;

如果表中不存在主键,那么MySQL就会查看当前表中是否存在非空唯一索引(无论是否为联合索引),如果存在,则以该联合索引作为聚簇索引;

如果以上两个条件都不满足,那么MySQL就会为表生成一个rowId作为聚簇索引。

       如下图所示是一个聚簇索引的简化示意图,可以看到,其和表结构基本是一致的:

1.2 二级索引

       对于二级索引,其也是以B+树的形式组织的,但其和聚簇索引最大的区别在于,其叶节点上不仅存储了当前索引列的数据值,还存储了该数据值所对应的磁盘数据的id。这里需要注意的是,如果磁盘有多条数据具有相同的值,那么在索引中其id会以列表的形式存储在叶子节点上。如下图所示为一个二级索引的示意图:

       上图中的二级索引即前面为name字段建立的索引。可以看到,该二级索引的叶节点中不仅保存有当前字段的数据值,还保存有该数据对应的磁盘数据的id。

       在使用二级索引进行查询时,MySQL首先会通过二级索引获取到所查询的数据对应的磁盘数据id,然后根据这些id在聚簇索引中查询磁盘数据,也就是说在使用二级索引进行查询时,其会进行两次索引的定位查询。如下图所示为使用二级索引进行查询的一个示意图:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyxxpj.html