MYsql优化where子句
该部分讨论where子句的优化,不仅select之中,相同的优化同样试用与delete 和update语句中的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:indexes 常量表达式只被计算一次:
5:没有where 条件的 单表 Count(*)直接检索Information_schema库中的统计信息(对 myisam 和 memory表)。
6:更早的察觉无效的常量表达式。mysql快速发现select语句中不可能成立的where条件并且返回no rows;
7: 如果没有使用group by 或者聚合函数(count(),min().max()),having子句会被合并到where 子句中;
8:做链接的每个table,一个快速的where子句构造原则是尽可能的跳过更多的行;
9:查询中,所有 constant table 都在其他表之前读取,constant table 定义如下:
1.1 : 一个空表或者只有一行数据的表;
1.2: 一个以主键 或唯一索引为 where条件子句的表,并且所有的Index部分都是和常量表达式比较,不为null(unique index 可能包含多个null);
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时优先read;
11:如果order by子句和 group by子句不同,或者order by Or group by 包含不在查询队列第一张表的中的列,那么会创建 temporary table;
12: 优化器如果认为使用index 会比表scan 更高效,则会选择使用index,scan表会被使用,如果最好的index需要scan多于30%的表记录,但是一个固定的比例不会确定使用table scan或者走index,优化器更加复杂,根据在额外的因数,eg:表的大小,行数,block快的大小;
13: 有些情况下,mysql 可以读取Index 数据而不必回访data file(base table)(索引覆盖);
下面的快速例子:
SELECT COUNT(*) FROM tbl_name; SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name; SELECT MAX(key_part2) FROM tbl_name WHERE key_part1=constant; SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... LIMIT 10;
SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC, ... LIMIT 10;
以下是mysql只查询 index B-Tree,假设index 列值为数值型:
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;
以下是用index来避免Filesort
SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... ; SELECT ... FROM tbl_name ORDER BY key_part1 DESC, key_part2 DESC, ... ;