1. B+树(索引数据结构)
什么是索引? 为什么索引能加快查询? 索引的数据结构是什么? B+ 树 和(B 树 和 红黑树)有什么区别? 为什么选择 B+树 作为索引数据结构?
为什么Mysql InnoDB选择B+ Tree作为索引?
- B+ 树 vs B 树 B+ 树只在叶子节点存储数据,B树的非叶子节点也要存储数据,所以B+ 树的单个节点的数据量更小
- B+ 树 vs 二叉树 对于有N个叶子节点的B+ 树,搜索复制度为O(logdn)
- B+ 树 vs Hash
2. 索引组织表(索引存储)
堆表和索引组织表有什么区别?
分别应用场景是什么?
Mysql InnoDB存储引擎中数据存储方式:索引组织表
数据存储有堆表和索引组织表两种。
堆表中的数据是无序存放的,数据的排序完全依赖索引
索引组织表,数据根据主键进行排序存放在索引中,主键索引也叫聚集索引(Clustered Index)
在索引组织表中,数据即索引,索引即数据
二级索引
InnoDB存储引擎的数据是根据主键索引排序存储的,除了主键索引外,其它的索引都称为二级索引(Secondeary Index),或者非聚集索引
二级索引也是一颗B+树索引,但是它和主键索引不同的是叶子节点存放的是索引键值、主键值
通过二级索引idx_name
只能定位主键值,需要额外再通过主键索引进行查询,才能得到最终结果。
这种二级索引通过主键索引进行再一次查询的操作叫做“回表”
这样的二级索引设计的好处:若记录发生了修改,则其它索引无须进行维护,除非记录的主键发生了修改
在索引组织表中,万物皆索引,索引就是数据,数据就是索引。
二级索引的性能评估
要比较顺序,对聚集索引性能友好
尽可能紧凑,对二级索引的性能和存储友好
函数索引(先了解)
…
3.组合索引(联合索引)
联合索引的结构是什么?
如果利用联合索引提升查询性能
组合索引(Compound Index)是指由多个列所组合而成的B+树索引
组合索引既可以是主键索引,也可以是二级索引,只是排序的键值从1个变成了多个,本质还是一棵B+树索引
索引覆盖
目的是为了避免回表,由于二级组合索引的叶子节点,包含索引键值和主键值,若查询的字段在二级索引的叶子节点中,则可以直接返回结果,无需回表。
这种组合索引避免回表的优化手段称为索引覆盖(Covering Index)
4.索引失效
有哪些索引失效的场景?
为什么会失效?
前提:索引可以提高语句查询速度,但是索引并不是万能的,建立了索引,并不意味着任何查询语句都能走索引扫描
索引存储结构长什么样?
MySQL默认的存储引擎是InnoDB,采用的是B+树作为索引的数据结构。在建表的时候,InnoDB存储引擎默认会创建一个主键索引,也就是聚簇索引,其它索引都属于二级索引
失效情况
A. 对索引使用左或者左右模糊匹配
索引B+树是按照索引值有序存储的,只能根据前缀进行比较
B. 对索引使用函数
索引保存的是索引字段的原始值,而不是经过函数计算后的值
C. 对索引进行表达式计算
原因与索引使用函数差不多,进行了表达式计算后得到的值不是原本的值,无法走索引
D. 对索引隐式类型转换
Mysql的类型转换规则:
字符串 –> 数字,就相当于 数字比较
数字 –> 字符串,就是字符串比较
小总结:在Mysql中,遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较
E. 联合索引非最左匹配
F. Where 子句中的OR
在WHERE子句中,如果在OR前的条件列是索引列,而OR后面不是索引列,那么索引会失效
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索引出错:
未使用创建的索引
索引创建在有限状态上
6.索引应用
建立索引有什么优点和缺点?
如何正确使用索引?
哪些场景下适合建立索引?
哪些场景下不适合建立索引?
总结
B+树索引
索引的加快查询的一种数据结构,其原理是插入时对数据排序,缺点是会影响插入的性能
Mysql当前支持B+树索引、全文索引、R树索引
B+树索引的高度通常为3~4层,高度为4的B+树可以存放50亿左右的数据
由于B+树的高度不高,查询效率高,50亿的数据也只需插叙4次I/O
Mysql单表的索引没有个数限制,业务查询需要,创建即可
可以通过表sys.schema_unused_indexes和索引不可见特性,删除无用的索引
Mysql采用B+树索引?从数据结构、磁盘I/O操作次数出发
索引组织表
Mysql InnoDB存储引擎是索引组织表,以及索引组织表和堆表之间的区别:
索引组织表主键是聚集索引,索引的叶子节点存放表中一整行完整记录
除主键索引外的索引都是二级索引,索引的叶子节点存放的是(键值,主键值)
由于二级索引不存放完整记录,因此需要通过主键值再进行一次回表才能定位到完整数据
索引组织表对比堆表,在海量并发的OLTP业务中能有更好的性能表现
每种不同数据,对二级索引的性能开销影响不一样
有时通过函数索引可以更快解决线上SQL的性能问题
虚拟列不占用实际存储空间,在虚拟类上创建索引本质就是函数索引
组合索引
组合索引也是一颗B+树,只是索引的列由多个组成,组合索引既可以是主键索引,也可以是二级索引
组合索引的三大优势
覆盖多个查询条件,如(a,b)索引可以覆盖查询 a = ? 或者 a = ? and b = ?
避免SQL的额外排序,提高SQL性能,如WHERE a = ? OR ORDER BY b 这样的查询条件
利用组合索引包含多个列的特性,可以利用索引覆盖技术,提高SQL的查询性能,用好索引覆盖技术,性能提升10倍不是难事
索引失效
6种会发生索引失效的情况:
使用左或者左右模糊匹配的时候,也就是
like %xx
或者like %xx%
这两种方式,都会造成索引失效当我们查询条件中对所有列使用
函数
,会导致索引失效在查询条件中对所有列进行
表达式运算
,会导致索引失效MySQL遇到字符串和数字比较的时候,会自动把字符串转为数字,再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么所有列会发生隐式类型转换,由于隐式类型转换是通过CAST函数实现的,等于对索引列使用了函数,所以导致索引失效
联合索引要能正确使用遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则索引会失效
在WHERE子句中,如果在OR前的条件列是索引列,而在OR后的条件列不是索引列,那么所有会失效
索引选择
MySQL优化器是CBO,是一种基于成本的优化器。会判断每个索引的执行成本,从中选择出最优的执行计划
MySQL优化器是CBO(Cost-based Optimizer)的
MySQL会选择成本最低的执行计划,可以通过explain命令查看每个SQL的成本
一般只对高选择度的字段和字段组合起来建立索引,选择度低的字段如性别,不建议建立索引
若数据存在倾斜,可以创建直方图,让优化器知道索引中的数据的分布,进一步校准执行计划
面试题:
1.为什么InnoDB选择B+Tree作为索引的数据结构?
B+树 vs B树
存储相同数据量级下,B+树高比B树低,磁盘I/O次数更少
B+树叶子节点用双向链表串起来,适合范围查询,B树无法做到这点
B+树 vs 二叉树
- 随着数据量的增加,二叉树的树高会越来越高,磁盘I/O次数也会更多,B+树在千万级别的数据量下,高度依然维持在3~4层左右
B+树 vs Hash
- 虽然Hash的等值查询效率高,但是无法做到范围查询
2.什么时候适用索引?
字段有唯一限制性
经常用于WHERE查询条件
经常用于GROUP BY 和 ORDER BY的字段
3.什么时候不需要创建索引?
WHERE条件,GROUP BY,ORDER BY里用不到的字段
字段中存在大量重复数据
表数据太少
经常需要更新的字段
4.什么时候索引会失效?
左或左右模糊匹配
在查询条件中对索引列做了计算、函数、类型转换等操作
联合索引要正确遵循最左匹配原则
在WHRER子句中,如果在OR前的条件是索引列而OR后的条件列不是索引列
为了更好使用索引,索引列要设置为NOT NULL
5.有什么优化索引的方法?
回答:
前缀索引优化
覆盖索引优化
主键索引最好是自增的
防止索引失效
#MySQL