什么是索引,索引就相当于一本书的目录。通过索引可以快速查找到对应的数据。
索引常见面试题:
1. 索引的分类:
按数据结构分类:
按物理存储分类:一般分为聚簇索引(主键索引),二级索引(辅助索引)
主键索引的B+树的叶子节点上一般存储的是数据,所有完整的用户数据都存放在主键索引的叶子节点上
二级索引的B+树的叶子节点上一般存储的是主键值,而不是实际数据。然后再通过主键值再查找到相应的数据,也就是说二级索引要经过两次查询。
回表:
如果在二级索引的第一次查询中获得相应的数据,就不需要再进行一次查询。这就叫做覆盖索引。如果第一次查询中没有获得相应数据,只获得主键值,那么就需要再进行一次主键检索。这个过程就叫做回表。
按字段特性分类:
主键索引:主键索引就是建立在主键上的索引,一般在建表的时候创建,一张表只能有一个主键索引,并且主键索引的列的值不允许为空值。
唯一索引:唯一索引建立在UNIQUE字段上的索引,一张表可以有多个唯一索引。索引列的值必须唯一,允许有空值。
普通索引:建立在普通字段上的索引,既不要求字段为主键索引,也不要求字段为唯一索引。
前缀索引:前缀索引是建立在字符型字段的前几个字符建立的索引。使用前缀索引的目的是减少索引占用的内存空间。提升查询效率。
按字段个数分类:
单列索引:建立在单列字段上的索引
联合索引:建立在多列字段上的索引(采用最左匹配原则)。
2. 什么时候需要创建索引 / 什么时候不需要创建索引
索引的好处和缺点:
索引最大的好处就是提高查询速度。
索引的缺点:需要占用物理空间,数量越大,占用空间越大。
创建索引和维护索引需要耗费时间,这种时间随着数据量的增大而增大。索引就是典型的以空间换时间
会降低表的增删改查的效率,每次增删改查,B+数为了维护索引有序性,都要进行动态维护。
什么时候需要创建索引:
字段有唯一性限制,就像商品编码
经常用于where 语句查询语句的字段,这样能够提高整个表的查询效率。如果查询字段不是一个,可以进行联合查询。
语句中含有ORDER BY和GROUP BY的字段,这样在进行查询时就不用去做一次排序。因为建立好索引之后,B+树上的数据都是有序的。
什么时候不需要查询数据:
WHERE 和 ORDER BY 和 GROUP BY 用不到的语句。
字段中出现大量的数据,比如性别字段,每次查询都只会出现一般的数据。
表数据太少的时候不需要创建索引
经常更新的字段,B+树需要维护数据的有序性,频繁的增删改查会影响数据库的性能。
3. 索引优化的方法:
前缀索引优化方法:前缀索引就是使用某个字段的前几个字符作为索引,在一些大的字段作为索引时,使用前缀索引可以减少索引项的大小。
覆盖索引优化:在二级索引的查询中,如果在第一次查询就获得相应的数据,就可以避免回表操作。方法:我们可以建立一个联合查询。即「商品ID、名称、价格」作为一个联合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表。
主键最好是自增的:如果我们将主键设置为自增的,那么每增加一次数据就会按顺序添加到对应的叶子节点上。不需要移动数据。每插入一次新数据,都是追加操作。
索引最好设置成NOT NULL:索引中出现NULL会让优化器在做索引选择时会更加麻烦。
NULL值是一个没意义的数据,但是会在行格式中的NULL值列表增加1KB的空间。
防止索引失效:
- 当我们使用左或者左右模糊匹配的时候,也就是
like %xx
或者like %xx%
这两种方式都会造成索引失效;- 当我们在查询条件中对索引列做了计算、函数、类型转换操作,这些情况下都会造成索引失效;
- 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
- 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
从数据页的角度看B+树
Innodb是如何存储数据的
Innodb是按照数据页的形式读取数据的(以行的形式效率会很低),每个页默认大小为16KB,意味着数据库每次读取数据都是以16KB为单位,一次最少读取16KB的数据到内存中。一次最少把内存中16KB的数据刷新到磁盘中。
数据页的主要作用就是存储数据,也就是数据库里的数据。数据页中的记录按照主键顺序组成单向链表。单向链表的优点主要是方便插入和删除。但是检索效率不高。
数据页中有一个页目录,起到记录的检索作用。
每个槽相当于指针指向了不同组的最后一个记录。、
页目录就是由多个槽准备的,槽相当于分组记录的索引。我们查找数据可以通过二分法快速定位到对应的槽,在遍历槽内的所有记录,从而找到对应的记录。
B+树是如何进行查询的
磁盘的I/O次数对索引的使用效率至关重要。因此,采用B+树是最合适的。
B+树中的每个节点都是一个数据页。
B+树中非叶子节点仅用来存放目录项来进行索引,B+树的叶子节点用来存放数据。
所有的节点按照索引键的大小排序,构成一个双向链表,便于范围查询。
为什么MySQL采用B+树的形式来存储数据
设计一个适合MySQL索引的数据结构需要满足以下几点
能在尽可能少的磁盘中进行I/O操作
能高效的查询一个记录,也要能高效的执行范围查找
什么是二分查找
二分查找每次都能将范围减半,时间复杂度会降低。
二分查找树
每一个节点的左子树的所有节点都小于这个节点。右子树的所有节点都大于这个节点。
自平衡二叉树
每个节点的左子树和右子树的高度差不能超过1 . 但是不管是平衡二叉树,随着插入数据的增多,树的高度也会增加。 也就意味着磁盘I/O的次数会增加。会影响整体查询效率。它每个节点都会有两个子节点。
B树
B树的每个子节点都会由多个子结点。降低了树的高度问题。
B+树
B+ 树与 B 树差异的点,主要是以下这几点:
- 叶子节点(最底部的节点)才会存放实际数据(索引+记录),非叶子节点只会存放索引;
- 所有索引都会在叶子节点出现,叶子节点之间构成一个有序链表;
- 非叶子节点的索引也会同时存在在子节点中,并且是在子节点中所有索引的最大(或最小)。
- 非叶子节点中有多少个子节点,就有多少个索引;