1. B+树(索引数据结构)

什么是索引? 为什么索引能加快查询? 索引的数据结构是什么? B+ 树 和(B 树 和 红黑树)有什么区别? 为什么选择 B+树 作为索引数据结构?

为什么Mysql InnoDB选择B+ Tree作为索引?

  1. B+ 树 vs B 树 B+ 树只在叶子节点存储数据,B树的非叶子节点也要存储数据,所以B+ 树的单个节点的数据量更小
  2. B+ 树 vs 二叉树 对于有N个叶子节点的B+ 树,搜索复制度为O(logdn)
  3. B+ 树 vs Hash

08 索引:排序的艺术

为什么 MySQL 采用 B+ 树作为索引?

2. 索引组织表(索引存储)

堆表和索引组织表有什么区别?

分别应用场景是什么?

Mysql InnoDB存储引擎中数据存储方式:索引组织表

数据存储有堆表和索引组织表两种。

  • 堆表中的数据是无序存放的,数据的排序完全依赖索引

  • 索引组织表,数据根据主键进行排序存放在索引中,主键索引也叫聚集索引(Clustered Index)

在索引组织表中,数据即索引,索引即数据

二级索引

InnoDB存储引擎的数据是根据主键索引排序存储的,除了主键索引外,其它的索引都称为二级索引(Secondeary Index),或者非聚集索引

二级索引也是一颗B+树索引,但是它和主键索引不同的是叶子节点存放的是索引键值、主键值

通过二级索引idx_name 只能定位主键值,需要额外再通过主键索引进行查询,才能得到最终结果。

这种二级索引通过主键索引进行再一次查询的操作叫做“回表”

这样的二级索引设计的好处:若记录发生了修改,则其它索引无须进行维护,除非记录的主键发生了修改

在索引组织表中,万物皆索引,索引就是数据,数据就是索引

二级索引的性能评估

  • 要比较顺序,对聚集索引性能友好

  • 尽可能紧凑,对二级索引的性能和存储友好

函数索引(先了解)

09 索引组织表:万物皆索引

3.组合索引(联合索引)

联合索引的结构是什么?

如果利用联合索引提升查询性能

组合索引(Compound Index)是指由多个列所组合而成的B+树索引

组合索引既可以是主键索引,也可以是二级索引,只是排序的键值从1个变成了多个,本质还是一棵B+树索引

索引覆盖

目的是为了避免回表,由于二级组合索引的叶子节点,包含索引键值和主键值,若查询的字段在二级索引的叶子节点中,则可以直接返回结果,无需回表。

这种组合索引避免回表的优化手段称为索引覆盖(Covering Index)

10 组合索引:用好,性能提升 10 倍!

MySQL夜市8月25日(联合索引)

4.索引失效

有哪些索引失效的场景?

为什么会失效?

前提:索引可以提高语句查询速度,但是索引并不是万能的,建立了索引,并不意味着任何查询语句都能走索引扫描

索引存储结构长什么样?

MySQL默认的存储引擎是InnoDB,采用的是B+树作为索引的数据结构。在建表的时候,InnoDB存储引擎默认会创建一个主键索引,也就是聚簇索引,其它索引都属于二级索引

失效情况

A. 对索引使用左或者左右模糊匹配

索引B+树是按照索引值有序存储的,只能根据前缀进行比较

B. 对索引使用函数

索引保存的是索引字段的原始值,而不是经过函数计算后的值

C. 对索引进行表达式计算

原因与索引使用函数差不多,进行了表达式计算后得到的值不是原本的值,无法走索引

D. 对索引隐式类型转换

Mysql的类型转换规则:

  • 字符串 –> 数字,就相当于 数字比较

  • 数字 –> 字符串,就是字符串比较

小总结:在Mysql中,遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较

E. 联合索引非最左匹配

F. Where 子句中的OR

在WHERE子句中,如果在OR前的条件列是索引列,而OR后面不是索引列,那么索引会失效

索引失效有哪些?

B+树里面的节点存放的是什么?查询数据的结果又是怎样的?

5.索引选择

Mysql数据库中的优化器是怎么执行的?

根据什么标准选择索引?

MySQL是如何选择所索引的?

在关系型数据库中,B+树索引只是存储的一种数据结构,具体使用还需要依赖数据库的优化器,优化器决定了具体某一索引的选择

优化器的选择是基于成本(cost),哪个索引的成本越低,优先选择哪个索引

Cost = Server Cost + Engine Cost
     = CPU Cost + IO Cost

先看MySQL数据库的结构,MySQL由Server层和Engine层组成:

  • Server层有SQL分析器、SQL优化器、SQL执行器,用于负责SQL语句的具体执行过程

  • Engine层负责存储具体的数据,常使用InnoDB存储引擎,还有用于内存中存储临时结果集的TempTable引擎

MySQL索引出错:

  1. 未使用创建的索引

  2. 索引创建在有限状态上

11 索引出错:请理解 CBO 的工作原理

6.索引应用

建立索引有什么优点和缺点?

如何正确使用索引?

哪些场景下适合建立索引?

哪些场景下不适合建立索引?

总结

  1. B+树索引

    1. 索引的加快查询的一种数据结构,其原理是插入时对数据排序,缺点是会影响插入的性能

    2. Mysql当前支持B+树索引、全文索引、R树索引

    3. B+树索引的高度通常为3~4层,高度为4的B+树可以存放50亿左右的数据

    4. 由于B+树的高度不高,查询效率高,50亿的数据也只需插叙4次I/O

    5. Mysql单表的索引没有个数限制,业务查询需要,创建即可

    6. 可以通过表sys.schema_unused_indexes和索引不可见特性,删除无用的索引

    7. Mysql采用B+树索引?从数据结构、磁盘I/O操作次数出发

  2. 索引组织表

Mysql InnoDB存储引擎是索引组织表,以及索引组织表和堆表之间的区别:

  • 索引组织表主键是聚集索引,索引的叶子节点存放表中一整行完整记录

  • 除主键索引外的索引都是二级索引,索引的叶子节点存放的是(键值,主键值)

  • 由于二级索引不存放完整记录,因此需要通过主键值再进行一次回表才能定位到完整数据

  • 索引组织表对比堆表,在海量并发的OLTP业务中能有更好的性能表现

  • 每种不同数据,对二级索引的性能开销影响不一样

  • 有时通过函数索引可以更快解决线上SQL的性能问题

  • 虚拟列不占用实际存储空间,在虚拟类上创建索引本质就是函数索引

  1. 组合索引

      组合索引也是一颗B+树,只是索引的列由多个组成,组合索引既可以是主键索引,也可以是二级索引

      组合索引的三大优势

    1. 覆盖多个查询条件,如(a,b)索引可以覆盖查询 a = ? 或者 a = ? and b = ?

    2. 避免SQL的额外排序,提高SQL性能,如WHERE a = ? OR ORDER BY b 这样的查询条件

    3. 利用组合索引包含多个列的特性,可以利用索引覆盖技术,提高SQL的查询性能,用好索引覆盖技术,性能提升10倍不是难事

  2. 索引失效

      6种会发生索引失效的情况:

    1. 使用左或者左右模糊匹配的时候,也就是 like %xx 或者like %xx% 这两种方式,都会造成索引失效

    2. 当我们查询条件中对所有列使用函数,会导致索引失效

    3. 在查询条件中对所有列进行表达式运算,会导致索引失效

    4. MySQL遇到字符串和数字比较的时候,会自动把字符串转为数字,再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么所有列会发生隐式类型转换,由于隐式类型转换是通过CAST函数实现的,等于对索引列使用了函数,所以导致索引失效

    5. 联合索引要能正确使用遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则索引会失效

    6. 在WHERE子句中,如果在OR前的条件列是索引列,而在OR后的条件列不是索引列,那么所有会失效

  3. 索引选择

MySQL优化器是CBO,是一种基于成本的优化器。会判断每个索引的执行成本,从中选择出最优的执行计划

  • MySQL优化器是CBO(Cost-based Optimizer)的

  • MySQL会选择成本最低的执行计划,可以通过explain命令查看每个SQL的成本

  • 一般只对高选择度的字段和字段组合起来建立索引,选择度低的字段如性别,不建议建立索引

  • 若数据存在倾斜,可以创建直方图,让优化器知道索引中的数据的分布,进一步校准执行计划

面试题:

1.为什么InnoDB选择B+Tree作为索引的数据结构?

  1. B+树 vs B树

    1. 存储相同数据量级下,B+树高比B树低,磁盘I/O次数更少

    2. B+树叶子节点用双向链表串起来,适合范围查询,B树无法做到这点

  2. B+树 vs 二叉树

    1. 随着数据量的增加,二叉树的树高会越来越高,磁盘I/O次数也会更多,B+树在千万级别的数据量下,高度依然维持在3~4层左右
  3. B+树 vs Hash

    1. 虽然Hash的等值查询效率高,但是无法做到范围查询

2.什么时候适用索引?

  • 字段有唯一限制性

  • 经常用于WHERE查询条件

  • 经常用于GROUP BY 和 ORDER BY的字段

3.什么时候不需要创建索引?

  • WHERE条件,GROUP BY,ORDER BY里用不到的字段

  • 字段中存在大量重复数据

  • 表数据太少

  • 经常需要更新的字段

4.什么时候索引会失效?

  • 左或左右模糊匹配

  • 在查询条件中对索引列做了计算、函数、类型转换等操作

  • 联合索引要正确遵循最左匹配原则

  • 在WHRER子句中,如果在OR前的条件是索引列而OR后的条件列不是索引列

  • 为了更好使用索引,索引列要设置为NOT NULL

5.有什么优化索引的方法?

回答:

  • 前缀索引优化

  • 覆盖索引优化

  • 主键索引最好是自增的

  • 防止索引失效

  • #MySQL