前面讲了优化的实际操作,但是没有为何这么做可以优化,今天我们就解释下。

索引的原理

索引的作用相当于一本书的目录,通过关键字缩小目标内容的范围,从而加快定位目标数据的速度。
索引分为几种类型,常规有b-tree 索引、哈希索引等,日常开发大部分的索引都是 b-tree索引,本文讲的主要也是针对b-tree。

b-tree 索引的数据结构

b-tree 索引的数据结构是b+树
B+ 树的特点是

1.能够保持数据稳定有序
2.查找以典型的方式进行,类似于二叉查找树

btree
在数据库中,b+树 的数据存储在叶子节点,父节点没有任何的数据内容,如图所示。b-tree的查找过程是,如图,比如说要找到28,先是从最顶端开始,将顶节点所在的从磁盘读入内存,然后找到P2,将P2所在的磁盘读入内存,然后找到数据在P2对应子节点所在的磁盘,最后将找到的目标磁盘读入内存,完成查找。中间总共发生了 3次磁盘IO。磁盘IO次数越多,越耗性能。所以在设计索引的时候需要注意,尽量避免b-tree 的高度过高导致性能下降。

慢查询原则解释

(1)优先创建联合索引 再考虑加单独的字段索引
大多数业务表的查询,都是会有多个条件查询过滤的,建立联合索引,能够将索引范围对应的叶子节点的数量降低,让最后一次IO将磁盘数据加载到内存速度大大提升,本质上就是扫描的数据行数低。而多个单列索引,使用到的只能是一个索引,该索引对应的叶子节点数量比联合索引的多,因此效率低。

(2)同一张表,不同数据量,同样的SQL语句可能的执行顺序不一致,索引使用可能不一致
mysql的逻辑架构中,很重要一环就是优化器对mysql查询语句的优化,
mysqlOp 优化器可以决定表的读取顺序,选择索引。一般来说如果有多个单列索引,优化器会选择扫描数据量较少的索引,但优化器也会根据历史的查询记录等条件进行分析,所以,最终使用到的索引也不一定是扫描量最少的索引。对于mysql来讲,它只会计算来获取一个最低成本执行该SQL语句的执行计划但并不是相应时间最低的。
在上次事故中就有遇到过,线上mysql优化器选择了一个数据量比较大的索引,导致慢查询,然后是采用了force index 强制使用某个索引来改进,效率大约提升了10倍左右。
如果想获取mysql优化过后的执行计划,可以通过 explain extended 来处理 SQL语句,然后再执行 show warnings 来显示执行计划。

(3)建索引时,优先采用区分度搞的字段,比如 status这种字段就没必要建索引
使用status这种区分度很低的字段时,使用单个status字段作为过滤条件,explain 查询语句,发现有用到 status的索引,扫描的行数也相对全表扫描的低;去掉status索引,explain,做了全表扫描,扫描的行数也很多。但是,查询使用的时间是差不多的,也就是,有无status索引效率是差不多的。反而,加了status索引,一会占用磁盘空间,二会降低update insert的效率。

(4)