MySQL datetime index не работает - PullRequest
       20

MySQL datetime index не работает

13 голосов
/ 25 октября 2010

Структура таблицы:

+-------------+----------+------+-----+---------+----------------+
| 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 использовал индекс независимо от того, какую дату я поставил?

Ответы [ 2 ]

11 голосов
/ 25 октября 2010

Здесь есть две вещи -

  1. Индекс недостаточно избирателен - если индекс охватывает более ок.30% строк MySQL решит, что полное сканирование таблицы более эффективно.Когда вы сокращаете диапазон, индекс начинает действовать.

  2. Один индекс на таблицу в объединении

Реальный запрос - намного большедлиннее с большим количеством объединений таблиц, точка ...

Дело именно в том, что у него есть объединения, которые, вероятно, не могут использовать этот индекс.MySQL может использовать один индекс на таблицу в объединении (если только он не подходит для оптимизации index-merge ).Если первичный ключ уже используется для объединения, время не будет использовано.Чтобы использовать его, вам нужно создать многостолбцовый индекс для ключа соединения + индекс времени выполнения в правильном порядке.

Проверьте EXPLAIN фактического запроса, чтобы увидеть, какой ключ MySQL использует для объединения,Измените этот индекс, включив в него также столбец thedatetime, или создайте новый многостолбцовый индекс из обоих (в зависимости от того, для чего вы используете ключ объединения).

7 голосов
/ 25 октября 2010

Все работает как положено. :)

Индексы предназначены для ускорения поиска. Они делают это с помощью поиска по индексу.

В первом запросе индекс не используется, потому что вы получаете ВСЕ строки, и в этом случае использование индекса медленнее (lookup index, get row, lookup index, get row ... x количество строк медленнее, чем get all rows == сканирование таблицы)

Во втором запросе вы получаете только часть данных, и в этом случае сканирование таблицы происходит намного медленнее.

Задача оптимизатора - использовать статистику, которую СУБД хранит в индексе, для определения наилучшего плана. В первом случае индекс был рассмотрен, но планировщик (правильно) выбросил его.

EDIT
Возможно, вы захотите прочитать что-то вроде this , чтобы получить некоторые понятия и ключевые слова, касающиеся планировщика запросов mysql.

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