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

来源:互联网 发布:吴梅村 红楼梦 知乎 编辑:程序博客网 时间:2024/06/03 04:57
这部分讨论的优化是针对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)。
阅读全文
0 0
原创粉丝点击