您的位置:首页 > 数据库 > MySQL

mysql5.7官网直译SQL语句优化--where条件查询优化

2017-11-07 18:53 555 查看
这部分讨论的优化是针对WHERE条件的。通过SELECT语句来举例,但是同样的优化也适用于DELETE和UPDATE中的WHERE语句。

   注意:因为mysql优化器的工作一直在继续,所以不可能把mysql执行优化的全部信息都展示在这里。

你也许会在牺牲可读性的前提下重写查询从而来提高算法操作速度。因为mysql会自动去做同样的优化操作,所以你应该避免这样做,从而保证你的查询更加可理解且具有更加可维护的格式。mysql完成的一些优化如下:

>移除不必要的括号;

例如:((a AND b) AND c OR (((a AND b) AND (c AND d))))-> (a AND b AND c) OR (a AND b AND c AND d)

>合并常数;

例如: (a<b AND b=c) AND a=5-> b>5 AND b=c AND a=5 #因为a是常数5,所以将b>a优化为b>5

>去除常数条件(如果是合并常数需要的话):

例如:(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)-> B=5 OR B=6 #第一个括号内的条件等价于B=5,而第二个括号内的条件等价于B=6,所以最终优化为后者形式的条件查询

>在索引中使用的常量表达式只会被评价一次。

>对一张简单表执行不带WHERE条件的count(*)查询,对于myisam和内存表而言,结果直接从表信息中获取。当然这个也可以同样完成,对于任何单表的NOT NUll表达式查询。

>对于非常量表达式的早期检查,mysql很快发现一些select语句是不可能有结果返回的。

>将having条件和where条件合并,如果你没有使用group by或者其他聚合函数的话(count(),min(),max()等)。

>对于连接中的每张表,一个简单的where条件被创建,只为更快的where 评估和尽可能的过滤无用数据。

>所有的常量表应该在查询中任何其他表读取之前读取。常量表可能是如下:

  1)一个空表或者是只有一行的表

  2)在主键或者是唯一索引列上使用了where条件的表,即全部索引和常量表达式比较并且被定义为非 NULL

  所有下列表都将被看为是常量表:

  select * from t where primary_key=1

  select * from t1,t2 where t1.primary_key=1 and t2.primary_key=t1.id;

>通过尝试所有可能的表连接从而找到最优的表连接。如果在order by 和group by条件中的列都是来自同一张表,那么该表应该首先被连接。

>如果order by和group by 条件是不同的列,或者是order by或者group by中的列来自其他表,而不是第一张连接队列中的表,则会创建一张临时表。

>如果你使用了SQL_SMALL_RESULT调整器,mysql会使用一个内存临时表。

>除非优化器相信表扫描会更有效,否则一定会查询每张表的索引,并且使用最好的索引来完成查询。曾经,是否要使用全表扫描的依据是最好索引是否超越表中的30%,但现在已经没有一个固定的比例来决定是使用索引还是全表扫描。现在的优化器更加复杂,所以选择条件也包含了一些额外因子比方说表大小,表中的行数,和I/O块的大小。

>在一些情况下,MYSQL能够查询行数据通过索引,而不用查询数据文件。如果索引中的全部列都是数字,那么只需要解析索引数就可以完成查询。

>在每一行输出之前,那些在having条件没有匹配上的行就会被忽略掉。

一些查询特别快的例子如下:

select count(*) from tb1_name;

select min(key_part1),max(key_part1) from tb1_name;

select max(key_part2) from tb1_name where key_art1=constant;

select .... from tb1_name order by key_part1,key_part2,... limit 10;

select .... from tb1_name order by key_part1 desc,key_part2 desc,... limit 10;

mysql只会使用索引树来解析下列查询,假设索引列是数字:

SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;

SELECT COUNT(*) FROM tbl_name

  WHERE key_part1=val1 AND key_part2=val2;

SELECT key_part2 FROM tbl_name GROUP BY key_part1;

下列查询通过索引来查询行,而不需要单独再排序一次。

到此关于where条件优化的解析就结束了。接下来要说明的是8.2.1.2的范围优化(range optimization)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql select 优化 where