在< >中,它使用覆盖索引来优化这样的限制查询。我使用从官方网站下载的sakila数据库。以下是查询:
SELECT a.film_id, a.description
from sakila.film a
inner join (
select film_id
from sakila.film b
order by title limit 50,5
) as lim
USING(film_id)但是我使用解释来分析这个过程。它看起来像这样。

在第三行中,它显示它仍然扫描所有1000行。然后,我测试了子查询select film_id from sakila.film b order by title limit 50,5,解释日志如下所示

。
在我的观点中,第一条日志中的第三行应该像第二条日志一样,我不知道如何解释第一条日志中的前2行,为什么行是55行和1行,我认为它们应该是5和5。这是MySQL官方演示。我想是因为mysql的版本。
我将mysql更新为8.0.11.0,它更正常一些,如下所示

我在mysql8.0和mysql5.6中测试了相同的数据集,在mysql5.6中,检索数据只需要0.2s,而在mysql8.0中则需要1s。他们有什么不同?第一行仍然是905,而不是5。有人能告诉我为什么第一行是905,第二排是1吗?
发布于 2018-05-19 00:27:53
EXPLAIN因忽略LIMIT值而臭名昭著。
这里有一种更好的方式来了解正在发生的事情:
FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';对一些数据使用类似的查询(对5.6) .
SELECT city, province, population
FROM canada AS a
JOIN ( SELECT id
FROM canada
ORDER BY city
LIMIT 300,20 -- I used bigger numbers
) AS x USING(id);(该表有5484行。)
mysql> SHOW SESSION STATUS LIKE 'Handler%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Handler_commit | 1 |
| Handler_delete | 0 |
| Handler_discover | 0 |
| Handler_external_lock | 4 |
| Handler_mrr_init | 0 |
| Handler_prepare | 0 |
| Handler_read_first | 1 |
| Handler_read_key | 21 | -- about 20
| Handler_read_last | 0 |
| Handler_read_next | 319 | -- about 300+20 (OFFSET+LIMIT)
| Handler_read_prev | 0 |
| Handler_read_rnd | 0 |
| Handler_read_rnd_next | 21 | -- about 20
| Handler_rollback | 0 |
| Handler_savepoint | 0 |
| Handler_savepoint_rollback | 0 |
| Handler_update | 0 |
| Handler_write | 20 | -- 20 (the 'derived' table)
+----------------------------+-------+
18 rows in set (0.00 sec)解释:
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 320 | NULL |
| 1 | PRIMARY | a | eq_ref | id | id | 4 | x.id | 1 | NULL |
| 2 | DERIVED | canada | index | NULL | city_id | 771 | NULL | 5484 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+所以..。没有桌子扫描。OFFSET仅包含在派生表中。
Using index在您的EXPLAIN (和我的)确认使用“覆盖索引”。
(我想……)在旧版本中,EXPLAIN实际上会计算任何派生表;8.0避免了这种情况。这可以部分解释为什么解释在你的两个输出中发生了变化。
https://stackoverflow.com/questions/50174920
复制相似问题