Индекс MySQL datetime не работает
Структура таблицы:
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| total | int(11) | YES | | NULL | |
| thedatetime | datetime | YES | MUL | NULL | |
+-------------+----------+------+-----+---------+----------------+
Всего строк: 137967
mysql> explain select * from out where thedatetime <= NOW();
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+
| 1 | SIMPLE | out | ALL | thedatetime | NULL | NULL | NULL | 137967 | Using where |
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+
Реальный запрос намного длиннее с большим количеством объединений таблиц, дело в том, что я не могу заставить таблицу использовать индекс datetime
. Это будет сложно для меня, если я хочу выбрать все данные до определенной даты. Тем не менее, я заметил, что я могу заставить MySQL использовать индекс, если я выбираю меньший поднабор данных.
mysql> explain select * from out where thedatetime <= '2008-01-01';
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+
| 1 | SIMPLE | out | range | thedatetime | thedatetime | 9 | NULL | 15826 | Using where |
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+
mysql> select count(*) from out where thedatetime <= '2008-01-01';
+----------+
| count(*) |
+----------+
| 15990 |
+----------+
Итак, что я могу сделать, чтобы MySQL использовал индекс независимо от того, какую дату я положил?
Ответы
Ответ 1
Все работает так, как предполагается.:)
Индексы для ускорения поиска. Они делают это, используя индексные запросы.
В первом запросе индекс не используется, потому что вы извлекаете ВСЕ строки, и в этом случае использование индекса медленнее (lookup index
, get row
, lookup index
, get row
... x количество строк медленнее, чем get all rows
== сканирование таблицы)
Во втором запросе вы извлекаете только часть данных, и в этом случае сканирование таблицы происходит намного медленнее.
Задача оптимизатора - использовать статистику, которую RDBMS держит в индексе для определения наилучшего плана. В первом случае был рассмотрен индекс, но планировщик (правильно) отбросил его.
ИЗМЕНИТЬ
Вы можете прочитать что-то вроде this, чтобы получить некоторые понятия и ключевые слова в планировщике запросов mysql.
Ответ 2
Здесь есть две вещи -
-
Индекс не является достаточно избирательным - если индекс охватывает более ок. 30% строк, MySQL решит, что полное сканирование таблицы более эффективно. Когда вы сокращаете диапазон, индекс вступает.
-
Один индекс для таблицы в соединении
Реальный запрос намного длиннее с большим количеством таблиц, точка...
Точка именно потому, что у нее есть соединения, которые, вероятно, не могут использовать этот индекс. MySQL может использовать один индекс для каждой таблицы в объединении (если только он не соответствует index-merge оптимизации). Если первичный ключ уже используется для соединения, это время не будет использоваться. Чтобы использовать его, вам нужно создать индекс с несколькими столбцами в файле соединения + индекс времени в правильном порядке.
Проверьте EXPLAIN фактического запроса, чтобы узнать, какой ключ MySQL используется для соединения. Измените этот индекс, чтобы включить столбец thedatetime, или создайте новый индекс с несколькими столбцами от обоих (в зависимости от того, для чего вы используете ключ соединения).