Использование индекса datetime в предложении where MySQL - PullRequest
3 голосов
/ 29 мая 2020

У меня есть таблица с 200 миллионами строк, где индекс создается в столбце created_at, который является типом данных datetime.

show create table [tablename] output:

 create table `table`
 (`created_at` datetime NOT NULL)
 PRIMARY KEY (`id`)
 KEY `created_at_index` (`created_at`)
 ENGINE=InnoDB AUTO_INCREMENT=208512112 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'

created_at диапазоны от 2020-04-01 ~ 2020-05-28.

Я хочу получать только строки, которые выходят за рамки 2020-05-15 23:00: 00.

при запуске:

EXPLAIN SELECT created_at
          FROM table
         where created_at >= '2020-05-15 23:00:00';

он говорит, что выводит:

rows       Extra
200mil   Using Where

Я понимаю, что в RDMS, если строки индекса не упорядочены, но когда вы создаете индекс в столбце, он отсортирован, поэтому сразу после нахождения '2020-05-15 23:00:00' после этого он просто вернет все строки.

Кроме того, поскольку его мощность равна 7 мил, я подумал, что использование индекса будет лучше, чем полное сканирование таблицы .

Это потому, что я ввел дату в виде строки? но когда я пытаюсь

 where created_at >= date('2020-05-15 23:00:00');

, все равно.

и

 where created_at >= datetime('2020-05-15 23:00:00');

выводит синтаксическую ошибку.

Сделал mysql просто решил это было бы более эффективно выполнить полное сканирование таблицы?

EDIT:

с использованием equals

EXPLAIN SELECT created_at
          FROM table
         where created_at = '2020-05-15';

выходы:

key_len    ref     rows     Extra
  5        const    51 

В предложении where если я меняю строку на дату ('2020-05-15'), она выводит:

key_len    ref     rows     Extra
  5        const    51      Using index condition

означает ли это, что первый равный запрос не использовал индекс?

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Все ваши запросы будут использовать индекс по столбцу created_at. MySQL всегда использует индекс, если он соответствует предикату (ам) предложения where.

Вывод ваших explain s действительно указывает на то, что у вас нет этого индекса, то есть подтверждено выводом вашего create table.

Просто создайте индекс, и ваша база данных будет его использовать.

Вот демонстрация :

-- sample table, without the index
create table mytable(id int, created_at datetime);

--  the query does a full scan, as no index is available
explain select created_at from mytable where created_at >= '2020-05-15 23:00:00';
id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra      
-: | :---------- | :------ | :--------- | :--- | :------------ | :--- | :------ | :--- | ---: | -------: | :----------
 1 | SIMPLE      | mytable | <em>null</em>       | ALL  | <em>null</em>          | <em>null</em> | <em>null</em>    | <em>null</em> |    1 |   100.00 | Using where
-- now add the index
create index idx_mytable_created_at on mytable(created_at);

-- the query uses the index
explain select created_at from mytable where created_at >= '2020-05-15 23:00:00';
id | select_type | table   | partitions | type  | possible_keys          | key                    | key_len | ref  | rows | filtered | Extra                   
-: | :---------- | :------ | :--------- | :---- | :--------------------- | :--------------------- | :------ | :--- | ---: | -------: | :-----------------------
 1 | SIMPLE      | mytable | <em>null</em>       | index | idx_mytable_created_at | idx_mytable_created_at | 6       | <em>null</em> |    1 |   100.00 | Using where; Using index
0 голосов
/ 30 мая 2020

Если значения распределены равномерно, примерно 25% строк будут >= '2020-05-15 23:00:00' Да, Mysql предпочтет полное сканирование таблицы с использованием индекса, когда у вас есть такой большой процент от таблицы.

См. Почему MySQL не всегда использует индекс для запроса выбора?

В контексте DATE date('2020-05-15 23:00:00') совпадает с '2020-05-15'.

В контексте DATETIME datetime('2020-05-15 23:00:00') совпадает с '2020-05-15 23:00:00'.

Using index означает, что INDEX «покрывает», что означает, что весь запрос может быть выполнен полностью в BTree индекса - без обращения к BTree данных.

Using index condition означает совсем другое - это связано с небольшой оптимизацией, относящейся к двум уровням («обработчик» и «механизм» ") в дизайне MySQL. (Подробнее см. «ICP», также известный как «Изменение условий индекса».)

...