1、优化where语句
虽然是优化select语句的where条件;同时也适用于update和delete。还有要避免那些以牺牲可读性而进行的加快算术运算速度的优化,因为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)
|
★ 常量折叠(Constant folding):使用在现代编译器中的一种最优化技术
(a<b AND b=c) AND a=5
→
b>5 AND b=c AND a=5
|
★ 移除常量条件(常量折叠需要)
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
→
B=5 OR B=6
|
★ 由索引使用的常量表达式仅评估一次。
★ 在没有where条件的单表中,COUNT(*)直接从为MyISAM 和MEMORY表的表信息获取。对于NOT NULL表达式的单表也是这样。
★ 及早检测无效的常量表达式。MySQL快速检测到某些 不可能的并且不返回任何行的SELECT语句。
★ 如果不使用GROUP BY或聚合函数(
COUNT(),
MIN()等等),HAVING会被WHERE合并 。
★ 对于连接中的每个表,WHERE构造一个更简单 的表达式以快速 对标WHERE评估,并尽快跳过行。
★ 在查询中的所有常量表要先于其他表被读取。常数表是以下任何一项:
1)空表或只有一行的表
2)使用主键或唯一索引查询的表,所有索引部分与常量表达式比较,且被定义为NOT 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 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 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, ... ;
|