Mysql не использует индекс DATETIME, когда в таблице есть другие поля - PullRequest
3 голосов
/ 06 апреля 2011

Мне нужна помощь, чтобы понять это. Я пытаюсь заставить Mysql использовать индекс для поля DATETIME.

Mysql решает не использовать индекс, если в таблице есть другие (не используемые) поля. Рассмотрим два случая ниже:

Простая таблица с 2 полями работает нормально :

DROP TABLE IF EXISTS datetime_index_test;
CREATE TABLE  datetime_index_test (
id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
created DATETIME NOT NULL ,
PRIMARY KEY (id) ,
INDEX (created)
) ENGINE = InnoDB ;

INSERT INTO datetime_index_test (created) VALUES
('2011-04-06 00:00:00'),
('2011-04-06 01:00:00'),
('2011-04-06 02:00:00'),
('2011-04-06 03:00:00'),
('2011-04-06 04:00:00'),
('2011-04-06 05:00:00'),
('2011-04-06 06:00:00'),
('2011-04-06 00:00:00');

EXPLAIN SELECT * FROM datetime_index_test
WHERE created <= '2011-04-06 04:00:00';

+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table               | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | datetime_index_test | range | created       | created | 4       | NULL |    4 | Using where; Using index |
+----+-------------+---------------------+-------+---------------+---------+---------+------+------+--------------------------+

Простая таблица с 3 полями, не работает нормально :

DROP TABLE IF EXISTS datetime_index_test;
CREATE TABLE  datetime_index_test (
id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
created DATETIME NOT NULL ,
user int(10) unsigned DEFAULT 0,
PRIMARY KEY (id) ,
INDEX (created)
) ENGINE = InnoDB ;

INSERT INTO datetime_index_test (created) VALUES
('2011-04-06 00:00:00'),
('2011-04-06 01:00:00'),
('2011-04-06 02:00:00'),
('2011-04-06 03:00:00'),
('2011-04-06 04:00:00'),
('2011-04-06 05:00:00'),
('2011-04-06 06:00:00'),
('2011-04-06 00:00:00');

EXPLAIN SELECT * FROM datetime_index_test
WHERE created <= '2011-04-06 04:00:00';

+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table               | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | datetime_index_test | ALL  | created       | NULL | NULL    | NULL |    8 | Using where |
+----+-------------+---------------------+------+---------------+------+---------+------+------+-------------+

Наконец, мой вопрос; Может кто-нибудь объяснить мне, почему Mysql решает не использовать индекс?

1 Ответ

4 голосов
/ 12 апреля 2011

Это связано с тем, что я называю правилом 5%, основанным на ключевой совокупности (количество элементов кортежа).

Если вы индексируете таблицу, в которой существует однобокое количество элементов, MySQL Query Optimizer всегда будет выбирать путь наименьшего сопротивления.

ПРИМЕР: Если в таблице есть столбец с полами, количество элементов равно двум, M и F.

Что вы указали в такой колонке по полу? Вы обязательно получите два гигантских связанных списка.

Если вы загрузите миллион строк в таблицу с гендерным столбцом, вы можете получить 50% M и 50% F.

Индекс становится бесполезным во время оптимизации запроса, если количество элементов ключевой комбинации (совокупность ключей, как я ее сформулировал) составляет более 5% от общего числа таблиц.

Теперь, что касается вашего примера, почему два разных плана EXPLAIN ??? Я думаю, что MySQL Query Optimizer и InnoDB как команда тегов.

В первом CREATE TABLE таблица и индексы имеют одинаковый размер, хотя и небольшой, поэтому он решил в пользу индекса, выполнив сканирование индекса, а не полное сканирование таблицы . Имейте в виду, что неуникальные индексы содержат внутренний первичный ключ каждой строки (RowID) в своих записях индекса, что делает индексы практически того же размера, что и сама таблица.

Во втором CREATE TABLE, из-за введения другого столбца, пользователь, , вы теперь заставляете Оптимизатор запросов видеть совершенно другой сценарий: таблица теперь больше индексов . Следовательно, Оптимизатор запросов стал более строгим в интерпретации того, как использовать доступные индексы. Это пошло к правилу 5%, которое я упомянул прежде. Это правило с треском провалилось, и Оптимизатор запросов принял решение в пользу полного сканирования таблицы.

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