首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >覆盖索引不能优化mysql8.0中的极限查询

覆盖索引不能优化mysql8.0中的极限查询
EN

Stack Overflow用户
提问于 2018-05-04 12:24:38
回答 1查看 77关注 0票数 0

< >中,它使用覆盖索引来优化这样的限制查询。我使用从官方网站下载的sakila数据库。以下是查询:

代码语言:javascript
运行
复制
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吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-19 00:27:53

EXPLAIN因忽略LIMIT值而臭名昭著。

这里有一种更好的方式来了解正在发生的事情:

代码语言:javascript
运行
复制
 FLUSH STATUS;
 SELECT ...;
 SHOW SESSION STATUS LIKE 'Handler%';

对一些数据使用类似的查询(对5.6) .

代码语言:javascript
运行
复制
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行。)

代码语言:javascript
运行
复制
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)

解释:

代码语言:javascript
运行
复制
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| 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避免了这种情况。这可以部分解释为什么解释在你的两个输出中发生了变化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50174920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档