前置基础

阅读下文需掌握前置知识点:
执行计划(explain): https://www.yuque.com/yufeng-asaiy/bciqei/dr14aw
性能监控:https://www.yuque.com/yufeng-asaiy/bciqei/vmq8rc#lzEh1

优化细则

1.索引列不要参与表达式计算**

案例:下图中 actor_id 是索引
同样的select语句,只有红框部分不同。但是从执行计划上看,结果已经天差地别了。
首先type的档位差太多,其次rows的预估值差太多
image.png
总结:当使用索引列进行查询时,尽量不要使用表达式。应该把计算放到业务层而不是数据库层

2.索引长度越小越好

原因:innoDB每次往硬盘查询的量是16kb(操作系统规定每次查询最小4kb,或者是4kb的整数倍)
如果索引本身过长,就会导致每次查询的索引个数过少,增加了整体查询的IO访问量。
memo: 如果一定要用varchar,char,text等类型的字段做索引,可以用 字段名(n) 这样的形式,只取该字段的前几个字节做索引。如 city(7),就是取city字段的前7个字节做索引,即前缀索引

3.排序尽量通过索引来

前置信息:order by 排序一般需要加载进内存,然后进行排序的算法,数据量较大的情况下,非常消耗性能。

原因:如果order by后面跟着的是索引的话,因为当初索引是按照B+树这个数据结构存储的,B+树天然就是一种排序,所以无论是asc,还是desc,都是已经排好序了,直接拿来用就可以了。

需要注意的是,如果A,B,C形成组合索引。

where A=xxx order by B desc ,C desc; 这种也是可以的
where A=xxx order by B asc ,C desc; 这种就不行了,一下升一下降
where A=xxx order by B ,C ,D; 这种也不行,多了一个普通字段

memo:可以通过explain的Extra字段来查看排序情况,如果值是 Using filesort,这个就是最low,最原始的排序。

4.union all,in,or 推荐 in

案例
从执行计划上可以看出 union all 明显效率太低(要执行2个步骤),当然如果是union all 和 union比较的话,不推荐union,因为union 存在去重的步骤
image.png
从具体执行时间来看in比or快(当然这里数据量过小,差别不是很明显)
image.png

5.触发自动类型转换会使索引失效

  1. 案例<br />phone的类型是varchar,但是输入的时候没有带引号,mysql也能识别,可以看到执行计划上已经变成全表扫描了<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/502529/1601365737015-1bf25e1d-aaa0-41bb-bd0e-3ca8fe88e5c4.png#align=left&display=inline&height=428&margin=%5Bobject%20Object%5D&name=image.png&originHeight=428&originWidth=1676&size=295868&status=done&style=none&width=1676)

6. 明确只有一个结果时,用limit 1

首先回归 limit的本质,即限制输出,而非分页
当使用limit 1的时候,innoDB找到第一个结果之后就会直接中断后面操作。
如果没有加limit 1,innoDB找到第一个结果后,还会继续搜索操作