Mysql必知必会之索引选择

在日常生产中,一个表可能会存在多个索引,那么mysql在执行sql的时候是如何去判断该走哪个索引,或者是全表扫描呢?mysql在选择索引的时候会根据索引的使用成本来判断。

一条sql执行的成本大致分为两块

  • IO成本,因为这些页都是在磁盘的,要想去判断首先得加载到内存,MySQL规定加载一个页的成本为1.0
  • CPU成本,除了IO成本之外,还有条件判断的成本,也就是CPU成本。比如前面举的例子,你得判断加载的数据name = '赵六'符不符合条件,MySQL规定每判断一条数据花费的成本为0.2

全表扫描成本计算。对于全表扫描来说,成本计算大致如下。mysql会对表进行数据统计,这个统计是大概,不是特别准,通过show table status like '表名'可以查看统计数据

比如这个表大致有多少条数据rows,以及聚簇索引所占的字节数data_length,由于默认是16kb,所以就可以计算出(data_length/1024/16)大概有多少个数据页。所以全表扫描的成本就这么计算了

rows * 0.2 + data_length/1024/16 * 1.0

二级索引+回表成本计算

二级索引+回表成本计算比较复杂,他的成本数据依赖两部分扫描区间个数和回表次数。为了方便描述扫描区间,这里我再把上面的图拿上来

select * from `user` where name = '赵六';

对着图看!

查询条件name = '赵六'就会产生一个扫描区间,从id=4的赵六扫描到id=6的赵六。又比如假设查询条件为name > '赵六',此时就会产生一个从id=7的刘七开始直到数据结束(id=9的王九)的扫描区间。又比如假设查询条件为name < '李四' and name > '赵六',此时就会产生两个扫描区间,从id=2的张三到id=3的张三算一个,从id=7的刘七开始直到数据结束算另一个。所以扫描区间的意思就是符合查询条件的记录区间。二级索引计算成本的时候,mysq规定读取一个区间的成本跟读取一个页的IO成本是一样的,都是1.0。区间有了之后,就会根据统计数据估计在这些区间大致有多少条数据,因为要读写这些数据,那么读取成本大致就是 条数 * 0.2。所以走二级索引的成本就是 区间个数 * 1.0 + 条数 * 0.2。之后这些数据需要回表(如果需要的话),mysql规定每次回表也跟读取一个页的IO成本是一样,也是1.0。回表的时候需要对从聚簇索引查出来的数据进行剩余查询条件的判断,就是CPU成本,大致为 条数 * 0.2

所以回表的成本大致为 条数 * 1.0 + 条数 * 0.2

扫描二维码关注公众号,回复: 15484408 查看本文章

所以二级索引+回表的大致成本为 区间个数 * 1.0 + 条数 * 0.2 + 条数 * 1.0 + 条数 * 0.2

当索引的成本和全表扫描的成本都计算完成之后,mysql会选择成本最低的索引来执行。mysql对上述成本计算结果还会微调,但是微调的值特别小,所以这里我就省略了,并且这里也只是大致介绍了成本计算的规则,实际情况会更复杂,比如连表查询等等,有感兴趣的小伙伴查阅相关的资料

小结

总的来说,这一节主要是让你明白一件事,mysql在选择索引的时候,会根据统计数据和成本计算的规则来计算使用每个索引的成本,然后选择使用最低成本的索引来执行查询

原文来自于三友的java日记

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/131030953