数据库的索引在不同的搜索引擎里面有不同的体现,这里主要从MyISAM和InnoDB两个搜索引擎来入手。
MyISAM搜索引擎
- MyISAM引擎使用B+Tree作为索引结构
- 叶节点的data域存放的是数据记录的地址
以Col1为主键,则上图是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址,在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别。只是主索引要求key是唯一的,而辅助索引的key可以重复,如果我们在Col2上建立一个辅助索引,则此索引的结构,跟主键索引的结构没什么区别。
InnoDB搜索引擎
- InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同
- InnoDB引擎索引也叫聚集索引,他的关键字和数据在叶节点上,在一起存储
下图是主键索引的示意图,数据表每一行的数据内容,都是挂接到叶子节点的
InnoDB搜索引擎辅助索引与MyISAM索引的不同是,InnoDB的辅助索引data域存储相应记录主键的值而不是地址。如下图是将名称字段设置为辅助索引的示意图,挂接到叶子节点是主键索引的值
举个例子,如果我们要查询名称叫Alice的数据,会先通过辅助索引查询到,这条数据的主键是18,然后再通过主键索引进行搜索,找到主键是18的叶子节点,并将数据返回。所以,对于InnoDB搜索引擎,主键索引是非常关键和重要的
补充
- 一般需要一个自增的数字主键
- 为了避免出现二叉搜索树那种又高又偏瘫的结构,B+树是具有自平衡能力的。所以在插入数据的时候,有可能会导致整棵树的多个部分发生旋转、合并和拆分操作,同时频繁的移动、分页操作造成了大量的碎片。
- 自增的数字主键,会自动建立索引,在插入数据时,由于主键本身就是自增有序的可以尽量减少B+树为自平衡而做的旋转、合并和拆分操作,从而提高效率,也可以减少碎片的产生。字符串类型的主键,如果没有什么规律,会导致插入的时候比较随机,可能会导致较多的旋转、合并和拆分操作。
- 如果你没有建立任何主键,那么MySQL中InnoDB引擎是要求表必须有一个主键的。没有手动建立主键,MySQL会将选一个不包含null的字段将它当做主键,并建立索引,如果连这样的字段都没有,就会使用行号生成一个聚集索引,把它当做主键,这个行号大小为6bytes。所以最好还是建议新建一个自增的int类型的主键。
- MySQL不使用B-树而选择B+实现索引的原因
- B+树更适合基于范围的查询:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。
- B+树更便于遍历:由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
- B+树结构的检索性能更具有稳定性。由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
- B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。