文章目录
索引是数据库中对数据查询/检索的一种优化方案。
1、索引采用的数据结构
主要有Hash索引和B+ Tree 两种数据结构。
Mysql默认的InnoDB引擎中,默认的是B+ Tree。
2、为什么用B+ Tree?和Hash索引比起来有什么优缺点吗?
- Hash索引底层是hash表,hash表以一种键值对存储数据的结构;多个数据在存储关系上没有任何顺序关系,在区间查询时候无法直接通过索引查询,就需要进行全表扫描。所以Hash索引只能用于等值查询的场景。其他问题:Hash索引无法利用索引完成排序,不支持多列联合索引的最左匹配规则。存在哈希碰撞问题。
- B+ Tree是一种多路平衡查找树,他的节点本来就是有序的,所以对于范围查询的时候不需要进行全表扫描。
3、B+ 树的叶子节点。
B+ 树的叶子节点可能存储整行数据,也可能存储主键key的值;
- 聚簇索引 : 按照数据的物理存储进行划分。对于一堆记录来说,使用聚集索引就是对这堆记录进行堆划分,即主要描述的是物理上的存储。正是因为这种划分方法,导致聚簇索引必须是唯一的。聚集索引可以帮助把很大的范围,迅速减小范围。但是查找该记录,就要从这个小范围中进行扫描了;;
- 非聚簇索引:B+树中叶子节点存储了主键的值,也称为非主键索引。非聚集索引是把一个很大的范围,转换成一个小的地图,然后你需要在这个小地图中找你要寻找的信息的位置,最后通过这个位置,再去找你所需要的记录。
在查询数据的时候,聚簇索引一般会比非聚簇索引快,因为非聚簇索引查询数据查到的是主键的值,需要通过主键的值再对数据表进行一次查询,称这种情况为回表。
非主键索引也可以通过覆盖索引避免回表。
覆盖索引(covering index):一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。
执行一条查询语句的时候,如果在索引中就能够获得所需要的数据,就不用查到索引后,再回到数据表中操作,减少的I/O,提高了效率。
eg:
表covering_index_sample中有一个普通索引 idx_key1_key2(key1,key2)。
当我们通过SQL语句:select key2 from covering_index_sample where key1 = ‘keytest’;的时候,就可以通过覆盖索引查询到key2并返回,无需回表。
4、联合索引、最左匹配
因为最左匹配原则,我们在建立联合索引过程中,需要注意按照索引使用的频繁度高低和数值的离散程度高低按顺序从左向右边排列,如此能够做到尽量减少因为索引失效而进行顺序扫描的情况。
最左匹配原则:where 语句中的条件按照索引建立的字段顺序来使用(不代表and条件就必须按照顺序来写),如果中间某列没有条件,或使用like会导致后面的列不能使用索引。
-
什么字段适合创建索引?
- 经常作查询选择的字段
- 经常作表连接的字段
- 经常出现在order by, group by, distinct 后面的字段
-
什么情况下会发生索引失效而进行全表扫描?
- 最左边存在 ”%(任意字符)“ 的LIKE模糊查询,如”%abc%“、”%__“等等;
- OR语句前后没有同时使用索引字段;
- 数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int型);
- 对于多列索引,没有满足最左匹配原则
5、索引的缺点
主要从时间和空间考虑:
- 时间:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度;
- 空间:索引需要占物理空间。
6、MySql 5.6中对索引的优化
- 索引下推(Index Condition Pushdown)
MySQL 5.6引入了索引下推优化,默认开启。
使用SET optimizer_switch = ‘index_condition_pushdown=off’;可以将其关闭。
官方文档中给的例子和解释如下:
people表中(zipcode,lastname,firstname)构成一个索引
SELECT * FROM people WHERE zipcode=‘95054’ AND lastname LIKE ‘%etrunia%’ AND address LIKE ‘%Main Street%’;
如果没有使用索引下推技术,则MySQL会通过zipcode='95054’从存储引擎中查询对应的数据,返回到MySQL服务端,然后MySQL服务端基于lastname LIKE '%etrunia%'和address LIKE '%Main Street%'来判断数据是否符合条件。
如果使用了索引下推技术,则MYSQL首先会返回符合zipcode='95054’的索引,然后根据lastname LIKE '%etrunia%'和address LIKE '%Main Street%'来判断索引是否符合条件。如果符合条件,则根据该索引来定位对应的数据,如果不符合,则直接reject掉。有了索引下推优化,可以在有like条件查询的情况下,减少回表次数。
参考文章: