造成慢SQL可能的原因

  1. 无索引或者索引失效

  2. 锁等待

    • 行锁是基于索引加的锁,如果我们在更新操作时,索引失效,行锁也会升级为表锁
    • 除了锁升级还要注意死锁
    MyISAM最小支持表锁,所以不讨论了。InnoDB最小支持行锁,但也要注意锁升级。
    当一张表使用大量行锁,会导致失误执行率下降,匆匆而可能造成其它事务长时间锁
    等待和更多的锁冲突发生,致使性能严重下降,更有可能会将行锁升级为表锁。
    
  3. 不恰当的SQL语句

    • 例如select *操作一般都需要回表,除非where条件是主键。
    • 对非索引字段进行排序。
  4. 在大数据表中使用<LIMIT M,N>分页查询。

优化案例

image-20210810075506804

  • 思路:利用子查询优化分页查询

    select * from order where id > (select id from order order by order_no limit 10000,1) limit 20
    

    image-20210810075755409

优化select案例

MySQL Innodb默认创建主键时会创建主键索引,而主键索引属于聚簇索引,即在存储数据时,索引是基于B+,构成的,
而叶子节点存放的是数据。

假设存在order_no、status俩列联合索引,现在要查出order_no、status俩列的值,通常我们都是这
样子干的:
select * from order where order_no='xxx'  #效率低
select order_no、status from order where order_no='xxx' #正确
为什么*会效率低呢?因为order_no、status是联合索引,定位到这个索引并不包含这行所有的数据,此时
就需要通过主键索引回表去查找整行的数据了,注意回表。

select count(*)优化方案

MYISAM会有一个变量记录具体行数,但如果加了条件,InnoDB和MYISAM都一样,得老老实实去查,所以下面讨论的都是日常使用最多的InnoDB

  • 如果业务不要求精确值,可以explain,它不会真正去执行,只会返回个大概的值。
  • 如果想要精确值,而表的数据又多,可以在另一个地方维护一个变量,没增删的时候都记录下,曲线救国。

思考题

image-20210810101440596

  • 最佳回复

    image-20210810101523450

Q.E.D.


一个热爱生活的95后精神小伙