mysql执行流程
connector:主要负责处理客户端的连接、获取权限、维持、管理连接等
analyzer:主要负责词法分析、语法分析
optimizer:主要负责做优化,如选择合适的索引、判断条件执行的顺序、查表的顺序等等
actuator:主要负责校验权限、执行sql
索引
此处以mysql5.7为例
索引类型
索引总共有四种类型:
- BTREE
- HASH
- FULLTEXT
- SPATIAL
下面分别来介绍一下:
HASH
hash的基本结构是数组+链表,在mysql中也是如此,因此会存在hash冲突的情况,举例说明
select * from tableA where name='kevin'
如果我们在name字段上建立hash索引,那么
在执行上述sql的时候会先通过hash算法计算kevin的下标,然后从链表中选择目标数据
需要注意的事,如果我们的sql是
select * from tableA where name>'kevin'
这是hash索引就没办法了,hash索引不支持范围查询,这种情况会转化为全表扫描
ps.innodb引擎下会自动把hash索引转化为BTRE类型的索引,因此实际上innodb不支持hash索引
FULLTEXT
全文索引只支持char、varchar、text类型的字段,支持innodb引擎
创建语句如下
ALTER TABLE commpany_info ADD FULLTEXT INDEX idx_cname (company_name) WITH PARSER ngram;
使用全文索引
select * from commpany_info WHERE MATCH (company_name)AGAINST ('一路 一带');
建索引时会对字段按分词器进行分词,查询时通过分词查找结果
使用的较少了解即可
SPATIAL
空间索引使用较少,略过
BTREE
b树索引,这是Innodb默认使用B+树的索引结构。
先说下B树的基本结构,如下图
可以看到,B数一个节点可以存储多个元素,因此高度相对较低,而B+树则更进一步
可以看到B+树除了一个节点能储存多个元素之外,还会在叶子节点冗余非叶子节点的数据,且叶子节点之间用指针相连,因此B+树在范围查找上效率会更高
优化
- 排除缓存干扰
通过mysql执行流程可以发现,MySQL会先检查缓存,因此不排除缓存的干扰可能无法获取正确的sql执行时间。使用SQL_NO_CACHE排除缓存干扰
select SQL_NO_CACHE * from tableA
- 加索引
- explain 查看执行计划
EXPLAIN select * from commpany_info WHERE company_name='Renuka Feeds Private Limited';
type如果是ALL说明是全表扫描需要优化,一般正常使用索引会是ref
possible_keys表示mysql选择的索引
rows表示扫描的行数,数字越大,效率越低
Extra后文再说
4. 覆盖索引
在普通索引中索引上只保存了当前字段值以及主键值,因此如果我们执行如操作那在查询过程中会进行回表,从而降低查询速度
select * from commpany_info WHERE company_name='Renuka Feeds Private Limited';
为了避免回表,就有了覆盖索引的概念,我们可以把我们需要的字段都放在索引中(即联合索引),或者仅仅查询索引中包含的字段,如
select company_name from commpany_info WHERE company_name='Renuka Feeds Private Limited';
如何判断是否回表?我们可以执行explain,如果extra中出现"Using Index"则说明没有回表
- 联合索引
- 最左匹配
比如我们在A、B、C三个字段上建立联合索引,实际上我们建立了A、AB、ABC三个索引,因此我们使用A字段进行查找时会使用到索引,而是用B、C查找时不会使用索引 - 索引下推
这是Mysql帮咱们实现的,主要用于在非聚簇索引时的多条件查询减少回表
举例一张表中有索引index_name(colA,colB),执行sql select * from tableA where colA=1 and colB like ‘aa%’ 时会现在索引中过滤数据,然后再回表查询 - 普通索引/唯一索引
首先需要引入change buffer的概念,msyql执行更新操作时如果数据页在内存中则直接更新,否则将缓存操作更新在change buffer中;下次查询如果取到的需要更新的数据所在的数据页时,则把change buffer中的更新语句执行,写入数据页中。因此在写多读少的任务中适合使用change buffer
普通索引和唯一索引的主要区别在更新过程中,假设需要更新的数据页不在内存中,此时唯一索引由于要保证唯一性因此必须把数据页读到内存中,因此唯一索引不能使用change buffer,而普通索引可以。
结论:
对于写多读少的业务,数据写完后被立即访问的概率较小,在保证业务正常的前提下,推荐使用普通索引;其他情况推荐唯一索引 - 函数操作导致索引失效
- 隐式转换导致索引失效