什么是索引
索引是一种加快查询速度的数据结构。在生活中使用场景有很多, 比如我们平时使用字典查找汉字,一般是按照偏旁部首来定位在第几页或者是按照拼音来定位在第几页。 倘若如果我们从第一页开始查找,不知道要查到什么时候了,有了索引目录的帮助,大大的提升了查询和检索的效率。
mysql的索引
mysql数据库除了存储数据外,其中很重要的一环就是为数据建立索引。如果没有索引,那使用数据库里庞大的数据就显得很鸡肋。 mysql的索引分为普通索引,唯一索引,全文索引, 一般用的比较多的是前面两种。另外我们还会用到主键索引,也称聚集索引,主键ID和数据是存放在一起的,每个表只有一个聚集索引,可以是主键,如果没有主键,就会选择一个不为null的唯一列作为聚集索引,如果这样的列也没有,mysql会内置一个长度为6字节长的ROWID作为隐藏的聚集索引。
索引的底层数据结构
mysql的索引底层是采用了B+树的数据结构, 而并没有使用二叉树,平衡二叉树(AVL),红黑树, B树。 其最大目的是最大限度的提升查询效率。 B+树的特点就根节点与支节点不存储数据,只存储键值,最大限度的使分叉变多, 树高低。 一般3层树高就可以存储几千万的数据,对于日常的业务数据量来说是足够的。 同时数据只存放在叶子节点, 这里相较于B树的每个节点即存储了索引键值同时又存储了数据。 由于mysql的索引是以页为单位,倘若节点存储的数据,势必占据的空间大小会更多,而每一页的空间是有限的,所以会导致树的键值数量变少,分叉变少,导致的树的深度增加,IO次数变多。 而采用B+树, 非叶子节点只存储键值,会产生更多的分叉,叶子节点存储了数据,在叶子节点间前增加后互相指向对方的指针, 当遍历到叶子节点,就可以横向遍历一定范围内的数据,不需要再从根节点重新遍历,大大的提升了查询效率。
* 注意 *
由于数据存储在叶子节点上,即使通过索引在非叶子节点找到键值,但还是要遍历到叶子层,才可以拿到数据,也就是说访问磁盘的次数是一样的
联合索引
为多个列同时建立索引, 这样的索引满足最左匹配原则, 比如为(a,b,c)建立联合索引, 这样查询条件, 连接关联, 排序的列中的存在a,a b, a,b,c 都会命中该索引。 而只有 b, b c, c都不会用到索引
索引覆盖
如果查询的列以及被包含在某个索引的列里面,就不需要查到主键索引值后,再次到主键索引去检索一遍,这个过程就回表,所以查什么字段,就尽量覆盖这些字段
索引下推
对数据的过滤是在server层,对索引的过滤是在存储引擎当中。在使用联合索引当中, 如果在命中了索引后,如果索引中还包含了其他列查询条件,直接在存储引擎当中进行过滤, 按照过滤后对数据再进行一次回表操作,比如 联合索引 idx_xx(a,b), 查询语句select * from T where a = 123 and b > 2 ,此是如果开启了索引下推的配置,则命中联合索引idx_xx, 有100条记录,然后考虑到该联合索引还包含b,则按照b>2 进行过滤,得到30条记录, 接着那这最终的30条进行一次回表,得到结果。如果没有开启下推配置,是取出100条记录到server层,然后还有根据b > 2 ,再进行一次回表,其目的就是减少回表的次数,提升查询的效率
索引失效
CBO原则,mysql优化器会去计算一个使用代价,不一定走了索引就比全表扫描更快,与数据库版本,数据量等都有关系。
怎么去建立索引
- 对于常作为查询条件的列, 连接条件的列, 排序的列,强烈建议建立索引
- 常被更新的列不宜建立索引
- 离散程度不高的列,不宜建立索引,比如性别
- 建立覆盖索引,减少回表次数
- 不宜用无序的列值作为索引,容易导致页分裂, 所以还是使用有一定规律,连续的值,比如递增。
- 过长的字段建议使用全文索引
怎么去使用索引
- 隐试转换会导致失效
- 使用函数表达式会导致失效
- 负向查询
- like 后直接带%