MySQL优化

limit
现有表a,分页查找数据,SQL语句如下:

select * from a where phone='123'  order by id desc limit   90000,5

底层查询到90005,然后丢掉90000条,可想而知随着数值越大,执行效率越来越低,导致磁盘IO消耗过大。

优化方案1,SQL如下

select id from a where phone='123'  order by id desc limit   90000,5

通过使用覆盖索引,一次IO可以读取大量数据,降低磁盘IO次数。
优化方案2,SQL如下

select * from a id>= (select id from a  where phone='123'  order by id desc  limit 90000,1) limit 5
select * from  a join (select id from a  where phone='123'  order by id desc limit 90000,20) b ON a.id= b.id

采用覆盖索引,快速定位到id,然后回表查询该列所有数据。

连接查询
Nested-Loop join(嵌套循环连接),驱动表a,被驱动表b,原理如下

  1. 读取1行a表数据;
  2. 在a获取关联字段在b表查询;
  3. 取出b表满足条件的行,跟a表获得结果合并。
  4. 重复上诉1,2,3;

Block Nested-Loop join(块嵌套循环连接),驱动表a,被驱动表b,原理如下

  1. 读取a表数据到内存;
  2. 遍历b表一行数据,在内存与a数据对比;
  3. 重复步骤2。

NLJ适合有索引,BNLJ适合无索引。

in与exists

  • 在mysql8.0以前(5.7),使用exists(不走索引)效率低下,使用in效率高。
  • mysql 8.0 对 exists做出优化,效率跟in相当。

在mysql8.0.18版本新增的 explain format=tree 查看执行计划的方法。

EXPLAIN SELECT * FROM card WHERE  not EXISTS (SELECT phone FROM `user` WHERE card.phone =`user`.phone)
EXPLAIN format=tree SELECT * FROM card WHERE  not EXISTS (SELECT phone FROM `user` WHERE card.phone =`user`.phone)


被优化成了半连接,文献。

not in 在explain 分析结果:

EXPLAIN SELECT * FROM card WHERE phone  not in (SELECT phone FROM `user` WHERE card.phone =`user`.phone)

DEPENDENT SUBQUERY:依赖只查询,获取user表数据时候会依赖外表card数据,我现在user表找数据然后再去card表找匹配合适结果。效率相当低下,可以优化SQL成连接查询。参考

你可能感兴趣的:(MySQL优化)