一、单表索引
发现问题:该查询type
为ALL
,存在全表扫描问题,未使用到索引,并且存在Using filesort
,文件内排序问题,需要优化。
开始优化:
1、创建复合索引
ALERT TABLE ' article' ADD INDEX index_article_ccv ('category_id','comments','views')
或者
create index index_article_ccv on article('category_id','comments','views')
分析:实际使用到了复合索引,type
为range
,但是仍然存在存在Using filesort
,文件内排序问题。comments>1
这里是范围,范围以后索引会导致失效----后面会做详细处理。
说明当前建立的索引,不合适,因为存在comments>1
范围查询,导致文件内排序。
具体执行分析:
- type为range是可以接受的,但是extra中存在
Using filesort
,文件内排序问题,仍是无法接受的,但是为什么我们建立的索引没啥用呢? - 因为我们按照Btree工作原理,先排序
category_id
,若果遇到相同的category_id
则再排序comments
,如果再遇到comments
相同则排序views - 当
comments
字段在联合索引里处于中间位置时,因为comments>1
条件是一个范围值(range),mysql无法利用索引再对后面的views部分进行检索,即range类型查询字段后面的索引无效。
解决
绕过comments索引重新建立索引,删除之前创建的索引,创建新索引,
create index index_article_ccv on article('category_id','views')
二、两表
1、左连接
未使用索引的情况下为全表扫描
开始优化:
- 右表添加索引
左表为索引检索,右表为全表扫描 - 删除右表索引 , 左表添加索引
分析得出
明显左连接右表添加索引效果要好(ref>index)。这是由于左连接的特性决定的LEF JOIN
条件用于确定如何从右表搜索行,左边一定有。所以,左连接加右表。
2、右连接
因为RIGHT JOIN
条件用于确定如何从左表搜索行,右边一定都有,所以左边才是关键点一定要加索引。
总结:
左连接,索引建右表;右连接索引加左表。
三、三表连接
1、三表左连接
全部为全表扫描
- 建立索引
- 执行结果
后面2个type
都是ref
且rows优化很好,效果不错。因此索引最好设置在需要经常查询的字段中
总结:
- 尽可能的减少join语句中的NestedLoop的循环次数:“永远小结果集驱动大结果集”——小表驱动大表
- 优化 NestedLoop(嵌套循环)的内层循环
- 保证join语句中被驱动表上join条件字段已被索引
- 当无法保证被驱动表的join条件字段被索引且内存资源充足的前提下,不要吝啬joinbuffer的设置。