对码当歌,猿生几何?

MySQL索引优化(五)—— WHERE语句优化

平常我们可能会牺牲可读性来使计算变得更快而重写SQL。其实MySQL会做类似的优化操作,我们大可以避免这个工作,尽量在写SQL的时候更关注可维护性和可读性。MySQL通常会做对WHERE语句做下述的优化:

1、移除不必要的括号

   ((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)

2、常量合并

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

3、常数条件删除(由于常量合并)

 (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6

4、索引使用的常量表达式只计算一次

5、没有where语句的count(*)操作对于MyISAM和MEMORY表会直接从表信息里检索

6、提早发现无效的常量表达式,MySQL会很快的发现那些不可能实现的SQL或者无结果的SQL.

7、如果where语句中没有group by 或者聚合函数,having语句是要被合并到where语句中去的

8、对于join语句中的表,通常会构造一个更简单的where语句来更快地得到where语句评估,并且尽可能快的跳过记录。

9、一个SQL中的常量表,相对于其他表首先会被读取。常量表通常具有以下特征:

  • 空表或者只有一条记录的表

  • 使用了主键的表,或者使用了唯一索引的表,并且唯一索引中的所有部分都与常量相比较,并且非空。

  • 以下表示常量表:

SELECT * FROM t WHERE primary_key=1;
SELECT * FROM t1,t2
  WHERE t1.primary_key=1 AND t2.primary_key=t1.id;

10、最好的join表的时候,最好的联合是建立在所有可能的组合之上的。如果一个order by 和group by语句中的列都取自相同的表,那这张表将会优先被join.

11、如果order by 或者group by语句中的列不是来自于join语句中的第一张表,那么将会创建一张临时表。

12、如果使用 SQL_SMALL_RESULT 修饰,MySQL将会使用一张非内存的临时表

13、每个表索引都会被查询,然后选出一个最优的索引来使用。特殊情况下,如果优化器认为使用表扫描的方式时更高效,那么将不会使用索引。曾经,表扫描是否使用取决于使用最优索引是否会扫描超过表的30%,但是一个固定的百分比是不能决定是选择使用索引还是表扫描。现在的优化器更复杂,会综合考虑表的大小、记录条数以及IO块大小等情况

14、如果索引中包含所要查询的所有列,那么MySQL是不会访问数据文件的,仅使用索引数就可以支持这些查询

15、在每条符合条件的记录输出之前,会跳过那些不匹配having语句的记录