mysql优化器对sql语句的简化(条件简化、外连接消除、子查询优化)

大多数的sql语句由人工写完后都可以转换成某种比较高效的执行形式,称为查询重写。本质上就是mysql优化器觉得你写的sql语句不好,自己再重写一遍。那重写的规则是什么?

一、条件化简

1、移除不必要的括号

((a = 5 AND b = c) OR ((a > c) AND (c < 5)))

化简成: (a = 5 and b = c) OR (a > c AND c < 5)

2、常量传递

由and连接的表达式可以进行常量的传递,例如

a = 5

a = 5 AND b > a

简化成:a=5 and b>5

3、表达式计算(重点说明)

a=5+1

化简成a=6

重点说明:如果列出啊先再函数中:abs(a)>5或者-a<-8

如上面这种优化器不会尝试对这些表达式进行化简,而这些列上如果建立了索引执行计划也不会走索引。这种情况的特点就是再列上进行了运算,如果不在列上运算(a=5+1),不会影响。

4、having和where子句的合并

如果查询语句中没有出现sum、max等的聚合函数以及group by子句,优化器就会把having子句和where子句合并。

5、常量表

查询的表中⼀条记录没有,或者只有⼀条记录。

使⽤主键等值匹配或者唯⼀⼆级索引列等值匹配作为搜索条件来查询某个表。

优化器觉得这两种查询花费的时间特别少,少到可以忽略,所以也把通过这两种⽅式查询的表称之为常量表。

优化 器在分析⼀个查询语句时,先⾸先执⾏常量表查询,然后把查询中涉及到该表的条件全部替换成常数,最后再分析其余表的查询成本

SELECT * FROM table1 INNER JOIN table2     ON table1.column1 = table2.column2     WHERE table1.primary_key = 1;

优化成:

SELECT table1表记录的各个字段的常量值, table2.* FROM table1 INNER JOIN table2     ON table1表column1列的常量值 = table2.column2;

二、外连接消除

对于优化人员,我们知道:内连接的驱动表和被驱动表的位置可以相互转换,⽽左(外)连接和右(外)连接的驱动表和被驱动表是固定的。这就导致内连接优化器可以通过改变连接顺序来降低整体的查询成本,而外连接却无法优化连接顺序(驱动表不可改变)。

可能有些人不清楚内连接和外连接的区别:可以看我以前的文章详细介绍了连接的原理(待修改)-CSDN博客

外连接和内连接的本质区别就是:对于外连接的驱动表的记录来说,如果⽆法在被驱动表中找到匹配ON⼦句中的过滤条件的记录,那么该记 录仍然会被加⼊到结果集中,对应的被驱动表记录的各个字段使⽤NULL值填充;而内连接的驱动表的记录如果⽆法在被驱动表中找到匹配ON⼦句中的过滤条 件的记录,那么该记录会被舍弃

左连接

select * from lian left join score
on lian.id = score.id;

左连接执行计划

可以看到驱动表是lian表,该表由八万多条数据,而驱动表每一行都需要进行匹配,所以如果两个表进行内连接score会作为驱动表,但是左外连接,lian表作为驱动表。

怎么才能将score表作为驱动表呢,或者说换一种思路,外连接在什么情况下能转换成驱动表呢?

左外连接与内连接的转化

select * from lian left join score
on lian.id = score.id where score.id is not null;

可以看到他和内连接结果是相同的。

再看看执行计划

可以看到驱动表为score。

结论

以上说明外连接在where条件中规定被驱动表不为空的时候(或者规定score.id=某值)可以转换为驱动表 。

思考:

而我也问了经验颇深的开发,他说在开发环境中左外连接用到的几率是最大的,场景如:被驱动表的记录不完整,所以需要左外连接,查询出为记录为空的被驱动表,进行信息填写,所以说实际情况下,大概率不会在where条件中进行被驱动表的规定。但是对于以上的转化,优化人员也要清楚。

  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于优化 MySQL 查询慢的 SQL 语句,可以考虑以下几个方面: 1. 使用索引:确保表中的列上有适当的索引。通过分析查询执行计划,可以确定哪些索引被使用或未使用,并根据需要添加或修改索引。 2. 优化查询语句:检查查询语句是否可以优化。避免使用不必要的连接操作,使用合适的 JOIN 类型,避免使用过多的子查询或临时表。 3. 限制结果集大小:如果查询结果集非常大,但实际只需要部分结果,可以使用 LIMIT 关键字限制返回的行数。 4. 分页查询优化:对于需要分页的查询,尽量避免使用 OFFSET 关键字,它会导致 MySQL 跳过大量的行。可以使用游标或者优化查询语句结构来提高性能。 5. 缓存查询结果:对于经常被重复执行的查询,可以考虑使用缓存技术,如 Redis 或 Memcached。将查询结果缓存在内存中,可以减少对数据库的访问次数。 6. 查询字段优化:只选择需要的字段,避免不必要的数据传输和存储开销。可以使用 SELECT 指定具体字段,而不是使用 SELECT *。 7. 优化表结构:合理设计数据库表结构,避免冗余和不必要的复杂性。对于大型表,可以考虑分区、分表等技术来提高查询性能。 8. 定期优化和维护:定期分析数据库性能,并进行优化和维护操作,如重新生成索引、收集统计信息、清理无用数据等。 以上是一些常见的优化方法,根据具体情况选择适合的优化策略。可以通过 MySQL 的 EXPLAIN 关键字分析查询执行计划,找出慢查询的原因,并根据需要进行相应的优化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值