提前终止查询
在发现已经满足查询需求的时候,MySQL 总是能够立刻终止查询。一个典型的例子就是当使用了 LIMIT 子句的时候。除此之外,MySQL 在其他几类情况下也会提前终止查询。
发现了一个不成立的条件,这时 MySQL 可以立刻返回一个空结果
-- film_id 字段是 unsigned 整型
EXPLAIN SELECT * FROM film WHERE film_id = -1;
+-------------+------------------------------+
|id |1 |
+-------------+------------------------------+
|select_type |SIMPLE |
+-------------+------------------------------+
|table |NULL |
+-------------+------------------------------+
|partitions |NULL |
+-------------+------------------------------+
|type |NULL |
+-------------+------------------------------+
|possible_keys|NULL |
+-------------+------------------------------+
|key |NULL |
+-------------+------------------------------+
|key_len |NULL |
+-------------+------------------------------+
|ref |NULL |
+-------------+------------------------------+
|rows |NULL |
+-------------+------------------------------+
|filtered |NULL |
+-------------+------------------------------+
|Extra |no matching row in const table|
+-------------+------------------------------+
除此之外,MySQL 在执行过程中,如果发现某些特殊的条件,则会提前终止查询。当查询执行引擎需要检索“不同取值”或者判断存在性的时候,MySQL 都可以使用这类优化。例如,我们现在需要找到没有演员的所有电影:
找到没有演员的所有电影
EXPLAIN
SELECT
*
FROM
film
LEFT JOIN film_actor USING (film_id)
WHERE
film_actor.actor_id IS NULL
+-------------+------------------------------+
|id |1 |1 |
+-------------+------------------------------+
|select_type |SIMPLE|SIMPLE |
+-------------+------------------------------+
|table |film |film_actor |
+-------------+------------------------------+
|partitions |NULL |NULL |
+-------------+------------------------------+
|type |ALL |ref |
+-------------+------------------------------+
|possible_keys|NULL |idx_fk_film_id |
+-------------+------------------------------+
|key |NULL |idx_fk_film_id |
+-------------+------------------------------+
|key_len |NULL |2 |
+-------------+------------------------------+
|ref |NULL |sakila.film.film_id |
+-------------+------------------------------+
|rows |1000 |5 |
+-------------+------------------------------+
|filtered |100 |10 |
+-------------+------------------------------+
|Extra |NULL |Using where; Not exists|
+-------------+------------------------------+
这个查询将会过滤掉所有有演员的电影。每一部电影可能都会有很多的演员,但是上面的查询一旦找到任何一个演员,就会停止并立刻判断下一部电影,因为只要有一名演员,那么 WHERE 条件就会过滤掉这部电影。
类似这种“不同值/不存在”的优化一般可用于 DISTINCT、NOT EXIST() 或者 LEFT JOIN 类型的查询。
最后更新于