4.SQL优化之Where语句
1 优化Where语句
以下优化适⽤于使⽤SELECT语句,但相同的优化适⽤于DELETE和UPDATE语句中的WHERE⼦句。
为了优化查询,有时我们可能考虑牺牲程序可读性,但是MySQL在⽣成执⾏计划时会对SQL进⾏改写,所以我们不需要过度改写,尽量保证可读性,只有在性能⽆法满⾜的基础上在按照⾃我理解进⾏重写SQL,以下是⼏种MySQL⾃动进⾏的SQL改写的例⼦:
删除不必要的括号:
((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
恒定条件去除
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)-> B=5 OR B=6
索引所使⽤的常数表达式仅计算⼀次。
在没有Where条件的MyISAM和MEMORY存储引擎中统计count(*)时,计算是通过表定义计算获得,所以效率很⾼。使⽤⼀个not null的表达式也可以达到这个效果。
某些SQL是不可能返回rows的,MySQL会提前检测出来然后直接返回。
如果不使⽤GROUP BY或聚合函数(COUNT(),MIN()等),HAVING将与WHERE合并。
对于每⼀个表连接,构造⼀个更简单的Where条件已获得更好的执⾏计划,尽可能的跳过更多不需要扫描的⾏。
在执⾏所有查询之前,⾸先读取常量表(常量表定义如下):
空表或者只有1⾏数据的表
与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;
通过尝试所有可能性,可以到加⼊表格的最佳连接组合。 如果ORDER BY和GROUP BY⼦句中的所有列都来⾃同⼀个表,则在加⼊时⾸先⾸选该表。
如果存在ORDER BY⼦句和不同的GROUP BY⼦句,或者ORDER BY或GROUP BY包含连接队列中第⼀个表以外的表中的列,则会创建临时表。
如果使⽤SQL_SMALL_RESULT修饰符,MySQL将使⽤内存中的临时表。
⾸先查询每个表索引,并使⽤最佳索引,除⾮优化程序认为使⽤表扫描更有效。 在以前,根据最佳索引是否跨越表的30%来使⽤扫描,但固定百分⽐不再决定使⽤索引或扫描之间的选择。 优化器现在更复杂,并且基于其他因素(例如表⼤⼩,⾏数和I/O块⼤⼩)进⾏估算。
在某些情况下,MySQL甚⾄⽆需查阅数据⽂件即可从索引中读取⾏。 如果索引中使⽤的所有列都是数字,则仅使⽤索引树来解析查询。
在输出每⼀⾏之前,将跳过与HAVING⼦句不匹配的⾏。
⼀些查询效率较⾼的SQL样例
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_namesql语句优化方式
ORDER BY key_part1,key_part2,... ;
SELECT ... FROM tbl_name
ORDER BY key_part1 DESC, key_part2 DESC, ... ;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。