Индекс покрытия не может оптимизировать лимитный запрос в mysql8.0 - PullRequest
0 голосов
/ 04 мая 2018

В , он использует индекс покрытия для оптимизации лимита запроса, подобного этому. Я использовал базу данных sakila , загруженную с официального сайта MySQL. Вот запрос:

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)

Но я использую объяснение для анализа процесса. Похоже на это. enter image description here

В третьей строке показано, что он все еще сканирует все 1000 строк. Затем я протестировал подзапрос select film_id from sakila.film b order by title limit 50,5, журнал объяснения, подобный этому log1.

В моем мнении третья строка в первом журнале должна быть похожа на вторую, и я не знаю, как объяснить первые 2 строки в первом журнале, почему строки 55 и 1, я думаю, может быть, они должны быть 5 и 5. Это официальная демонстрация MySQL. Я думаю, это из-за версии mysql.

Я обновляю свой mysql до 8.0.11.0, он стал немного более нормальным, как этот enter image description here

Я тестировал один и тот же набор данных int mysql8.0 и mysql5.6, в mysql5.6 для извлечения данных требуется всего 0,2 с, а в mysql8.0 для этого нужны 1 с. Чем они отличаются? А также Первый ряд все еще 905, а не 5. Может кто-нибудь сказать мне причину и почему первый ряд 905, второй ряд 1?

1 Ответ

0 голосов
/ 19 мая 2018

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)

EXPLAIN:

+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| 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 избегает этого. Это может частично объяснить, почему Объясните изменилось в ваших двух выходах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...