赞
踩
主博客:
【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客
下一篇:
【MySQL精通之路】SQL优化(1)-查询优化(2)-范围查询优化-CSDN博客
本节讨论可用于处理WHERE子句的优化。
这些示例使用SELECT语句,但DELETE和UPDATE语句中的WHERE子句也适用相同的优化。
注意:
因为MySQL优化器的开发工作还在进行中,所以这里并没有记录MySQL优化器所有的优化。
您可能会试图重写查询以加快算术运算,同时牺牲可读性。
由于MySQL会自动进行类似的优化,因此您通常可以避免这项工作,并将查询保留为更易于理解和维护的形式。
MySQL执行的一些优化如下:
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
PS:会删除子运算是常量值的条件判断
在MySQL 8.0.14及更高版本中,这发生在准备阶段,而不是优化阶段,这有助于简化join连接。
有关更多信息和示例,请参见“outer join优化”。
4.索引使用的常量表达式只计算一次。
5.从MySQL 8.0.16开始,将检查数字类型的列与常数值的比较,并删除无效或超出范围的值:
- # CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
- SELECT * FROM t WHERE c ≪ 256;
- -≫ SELECT * FROM t WHERE 1;
有关更多信息,请参见“Constant-Folding优化”。
6.直接从MyISAM和MEMORY表的表信息中检索不带WHERE的单个表上的COUNT(*)。当只与一个表一起使用时,这也适用于任何NOT NULL表达式。
7.早期检测到无效常量表达式。MySQL很快检测到某些SELECT语句是不可能的,并且不返回任何行。
8.如果不使用GROUP BY或聚合函数(COUNT()、MIN()等),HAVING将与WHERE合并。
9.对于联接中的每个表,都会构造一个更简单的WHERE,以便快速评估表的WHERE值,并尽快跳过行。
10.所有常量表都是在查询中的任何其他表之前先读取的。常数表是以下任意一种:
空表或只有一行的表。
与PRIMARY KEY或UNIQUE索引上的WHERE子句一起使用的表,其中所有索引部分都与常量表达式进行比较,并定义为NOT NULL。
以下所有表都用作常量表:
- SELECT * FROM t WHERE primary_key=1;
- SELECT * FROM t1,t2
- WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
11.通过尝试所有的可能性来找到连接表的最佳连接组合。如果ORDER BY和GROUP BY子句中的所有列都来自同一个表,则在联接时首选该表。
12.如果存在ORDER BY子句和其他GROUP BY子句,或者ORDER BY或GROUP BY包含联接队列中第一个表以外的表中的列,则会创建一个临时表。
13.如果使用SQL_SMALL_RESULT修饰符,MySQL将使用内存中的临时表。
14.查询每个表索引,并使用最佳索引,除非优化器认为使用表扫描更有效。曾经,扫描是根据最佳索引是否占表的30%以上来使用的,但固定的百分比不再决定使用索引还是扫描之间的选择。优化器现在更复杂了,它的估计基于其他因素,如表大小、行数和I/O块大小。
15.在某些情况下,MySQL甚至可以在不查阅数据文件的情况下从索引中读取行。如果索引中使用的所有列都是数字列,则仅使用索引树来解析查询。
16.在输出每一行之前,将跳过那些与HAVING子句不匹配的行。
一些查询示例:
- 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 ... FROM tbl_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 MAX(key_part2) FROM tbl_name GROUP BY key_part1;
以下查询使用索引,按索引排序顺序检索行,而不需要单独的排序过程:
- SELECT ... FROM tbl_name
- ORDER BY key_part1,key_part2,... ;
-
- SELECT ... FROM tbl_name
- ORDER BY key_part1 DESC, key_part2 DESC, ... ;
主博客:
【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客
下一篇:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。