2011-12-29 2 views
1

Я ве получил эту таблицу:Простой вопрос MySQL индексации

CREATE TABLE IF NOT EXISTS `test1_nopart` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `idAccount` int(10) unsigned NOT NULL, 
    `data` mediumint(8) unsigned NOT NULL, 
    `date` date NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `date` (`date`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Я заполнить эту таблицу с 10 000 000 строк. передел по дате однороден

EXPLAIN SELECT * FROM `test1_nopart` WHERE date = "2014-03-04" 

Вот результату

id select_type table  type  possible_keys key  key_len  ref  rows  Extra 
1 SIMPLE  test1_nopart  ALL  NULL   NULL NULL  NULL 7875981  Using where 

=> без объяснения 3.6sec для результата 3000 строк (приблизительно)

Как вы можете видеть индекс не используется, и он не является частью столбца possible_keys!

тот же самый запрос с индексом покрытия способом

EXPLAIN SELECT date FROM `test1_nopart` WHERE date = "2014-03-04" 

результат:

id select_type  table  type  possible_keys key  key_len  ref  rows  Extra 
1 SIMPLE  test1_nopart index NULL   date  3  NULL 7875981  Using where; Using index 

=> без объяснения 2.8sec для результата 3000 строк (приблизительно)

Почему MySQL неправильно использует этот индекс (DATE) ???

Информация: - VM-сервер (наш DEV среда, я не знаю, что это аппаратный состав) - MySQL 5.5.8

SHOW INDEX FROM test1_nopart 

результат:

Table Non_unique Key_name Seq_in_index Column_name  Collation Cardinality  Sub_part Packed Null Index_type Comment  Index_comment 
test1_nopart 0 PRIMARY  1 id A 7875981  NULL NULL  BTREE   
test1_nopart 1 date 1 date A 6077 NULL NULL  BTREE   
  • На дату 2014-03-04 => 3134 строки
  • Суммарный (накопительный) => 7 875 488
  • Существует 2556 Differents «дата» значения в таблице
+0

Что выход 'SHOW INDEX FROM test1_nopart', особенно индекс кардинальным? Кроме того, почему имена столбцов называются зарезервированными словами MySQL? –

+0

Ой, кажется, что 6077 очень низок ... – nemenems

+0

Кардинальность - не настоящая проблема. Когда вы запускаете запрос 'SELECT COUNT (1) datecount,' date' FROM test1_nopart GROUP BY 'date' WITH ROLLUP;' вы увидите реальную мощность. Вы также увидите, сколько строк занимает 2014-03-14. – RolandoMySQLDBA

ответ

0

только догадка - может быть, это что-то делать со словом date.

Try, чтобы дать некоторые намеки на MySQL, которые вы хотите использовать поле, не зарезервированное слово:

SELECT date FROM `test1_nopart` WHERE `test1_nopart`.`date` = "2014-03-04" 
+0

не имеет никакого отношения к слову date, я пробовал с 'и он играл то же самое – nemenems

1

для MySQL Query Optimizer видит, что индекс Traversal индекса даты включает погружение в Кластеризованный Индекс (известный как gen_clust_index). В свете этого оптимизатор запросов MySQL определил, что проще выполнить полное сканирование таблицы в первом запросе и полное сканирование индекса в запросе scecond.

Возможно, вам также необходимо увидеть мощность индекса и количество строк в каждом отдельном значении.

Выполните следующие действия:

SELECT COUNT(1) datecount,`date` FROM test1_nopart GROUP BY `date` WITH ROLLUP; 

По вашему комментарию, вы получите 6077 различных строк. Вы также сказали, что около 10 000 000 строк.Запустите этот запрос вместо этого:

SELECT COUNT(1) datecount FROM test1_nopart WHERE `date` = '2014-03-14'; 

Обратите внимание на количество и общее количество.

5% от 10000000 составляет 500000

Если есть более, что 500000 строк с датой «2014-03-14», то MySQL не будет использовать индекс правильно для этого конкретного значения.

Я не доверяю SHOW INDEXES FROM test1_nopart;, потому что стол InnoDB. MyISAM будет показывать точное число. InnoDB производит номера на основе погружений в индекс.

Если дата даты любой даты превышает 5% от общего количества строк, MySQL Query Optimizer выкинет руки и выполнит полное сканирование.

UPDATE

OK, что 5% эмпирическое правило из окна. Попробуйте обмануть оптимизатор запросов MySQL, создав другой индекс покрытия:

ALTER TABLE test1_nopart ADD INDEX date_id_ndx (`date`,id); 

и попробуйте свои запросы снова.

+0

Я думаю, что я в этом случае, так как у меня очень низкая мощность (6077) – nemenems

+0

На дату 2014-03-04 => 3134 на общую сумму (rollup) 7 875 488 – nemenems

+0

Считаете ли вы, что это плохо? – nemenems

0

Вот мои мысли.

В первом случае, когда мы пытаемся получить data от date MySQL не использует индекс на date из-за очень низкой мощности. И оптимизатор использует следующее: - вторичный индекс - кластер для доступа к строке - таблица для получения данных.

Во втором случае, когда пытается получить date от date проще пройти через таблицы с использованием индекса, потому что MySQL может получить выборку данных из индекса тоже (я имею в виду MySQL может сканировать только индекс, а не всей таблицы, чтобы получить те же данные,). Используйте следующее: - вторичный индекс

Смежные вопросы