Почему EXTRA в Mysql EXPLAIN равен NULL? Почему> = используется условие индекса? - PullRequest
6 голосов
/ 18 июня 2020
mysql> CREATE TABLE `t` (
     `id` int(11) NOT NULL,
     `a` int(11) DEFAULT NULL,
     `b` int(11) DEFAULT NULL,
     PRIMARY KEY (`id`),
     KEY `a` (`a`),
     KEY `b` (`b`)
   ) ENGINE=InnoDB

есть таблица с именем t и два индекса с именами a и b. Вставить в t 100000 строк данных

mysql> create procedure idata()
  begin
   declare i int;
     set i=1;
     while(i<=100000)do
       insert into t values(i, i, i);
       set i=i+1;
     end while;
   end;
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;
mysql> call idata();

Я провожу несколько экспериментов, некоторые из них выглядят следующим образом

there are some experiments

Теперь я хочу знать;

(1) почему explain select * from t where a >= 90000; лишнее Using index condition? у него есть индексный ключ, но у него нет индексного фильтра и фильтра таблицы, так почему это Using index condition?

(2) почему explain select * from t where a = 90000; extra это NULL? необходимо иметь доступ к таблице, если в первом случае Using index condition, почему во втором не может быть Using index condition?

(3) почему explain select a from t where a >= 90000; extra - Using where; Using index? Я знаю, что он использует индекс обложки, поэтому у extra Using index; но почему extra имеет Using where? значит серверу нужно фильтровать данные? но механизм хранения уже вернул правильный, зачем серверу фильтровать?

Ответы [ 2 ]

2 голосов
/ 20 июня 2020

Во-первых, терминология ...

«Использование индекса» означает, что (в данном случае) INDEX(a) содержит все необходимые столбцы. То есть «индекс покрывает».

«Использование условия индекса» совсем другое. Внутренне это называется ICP (изменение условий индекса). Это относится к тому, проверяет ли «обработчик» выражение или «условие» (a> = 90000) передается Механизму (InnoDB) для выполнения работы.

Что касается «Использование где»; это все еще остается загадкой для меня, даже после того, как я использовал MySQL в течение 20 лет и просмотрел тысячи объяснений. Я игнорирую это.

Во всех 3 ваших случаях используется INDEX(a). На это в первую очередь указывает «ключ» («а» - имя ключа, а не столбец), «key_len» («5»: 4 байта INT плюс 1 для NULLable) и, во вторую очередь, "тип" (который не говорит "Все").

Далее

  • Если вы измените 90000 на 70000, вы можете обнаружить, что он переключится на сканирование таблицы. Зачем переключаться между BTree Индекса и BTree данных (через PRIMARY KEY). Оптимизатор предположит, что будет быстрее просто просканировать всю таблицу, игнорируя строки, которые не соответствуют предложению WHERE.

  • EXPLAIN FORMAT=JSON SELECT - дает вам гораздо больше информации . (Возможно, не так много информации для этого простого запроса.) Один полезный сюрприз состоит в том, что он покажет , сколько сортировок действительно относится к единственному упоминанию "filesort". (Возможно, простой способ сделать это - GROUP BY x ORDER BY y; то есть сгруппировать и упорядочить по разным столбцам.)

  • Explain редко имеет такие чистые числа, как ваш «10001». Обычно столбцы «строк» ​​являются приблизительными, иногда ужасными.

  • В медленном журнале записываются «Проверенные строки»; он, вероятно, скажет 10001 (или, может быть, только 10000) и 1 для ваших тестов. Для сканирования таблицы это будет полные 100 КБ.

  • Другой способ получить «Проверенные строки» - использовать значения STATUS «Обработчика». См. http://mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts

0 голосов
/ 18 июня 2020

В вашем первом и последнем запросах используется WHERE с неявным сравнением с другими строками, в этом случае он использует индекс и показывает его в дополнительном поле (диапазон типов).

Когда вы создать условие с результатами 0-1, он может получить к ним прямой доступ (поиск O (1)). Никакого сравнения или упорядочивания не происходит, просто возьмите одну строку и верните ее.

...