2013-04-09 3 views
1

Учитывая следующее -MySQL индексы когда несколько возможны

drop table if exists learning_indexes; 

create table learning_indexes (
    id INT NOT NULL, 
    col1 CHAR(30), 
    col2 CHAR(30), 
    col3 CHAR(30), 
    PRIMARY KEY (id), 
    index idx_col1 (col1), 
    index idx_col1_col2 (col1,col2) 
); 

explain 

select 
    col1,col2 
from 
    learning_indexes 
where 
    col1 = 'FOO' 
    and col2 = 'BAR' 

Почему MySQL выбрать idx_col1 над idx_col1_col2?

+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+ 
| id | select_type | table   | type | possible_keys   | key  | key_len | ref | rows | Extra  | 
+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+ 
| 1 | SIMPLE  | learning_indexes | ref | idx_col1,idx_col1_col2 | idx_col1 | 91  | const | 1 | Using where | 
+----+-------------+------------------+------+------------------------+----------+---------+-------+------+-------------+ 

Это моя версия информация -

+-------------------------+---------------------+ 
| Variable_name   | Value    | 
+-------------------------+---------------------+ 
| innodb_version   | 1.1.8    | 
| protocol_version  | 10     | 
| slave_type_conversions |      | 
| version     | 5.5.29    | 
| version_comment   | Source distribution | 
| version_compile_machine | i386    | 
| version_compile_os  | osx10.7    | 
+-------------------------+---------------------+ 

ответ

0

Я согласен с Floaf, что MySQL иногда выбирает неправильные индексы, но я не думаю, что это имеет место здесь. MySQL включает количество строк и структуру данных в свое решение, какой индекс выбрать.

Для такого простого запроса, как этот, MySQL, скорее всего, не будет использовать какой-либо индекс вообще, если таблица содержит менее 100 строк или даже пуста. Кажется, что вычислительно дешевле просто сканировать все строки таблицы, чем использовать индекс. В плане объяснения вы можете видеть, что в столбце «ключ» указано idx_col1, но столбец «Extra» не говорит «using index».

Если таблица содержит более 100 строк, MySQL начнет использовать idx_col1. План объяснения покажет вам это. Только тогда, когда в колонке 1 содержится более 100 строк, которые фактически содержат строку «FOO», MySQL заметит, что использование idx_col1 не уменьшает предварительный набор результатов достаточно, так как ему придется сканировать оставшиеся 100 строк для значения ' BAR 'в col2. Поэтому он переключится на idx_col1_col2.

Я не совсем уверен, как MySQL быстро решает, какой индекс использовать, но я думаю, что он имеет какое-то отношение к эвристике и мощности отдельных строк в индексе, то есть как «выборочная» индексированная строка ,

+0

спасибо. Я думал, что «использование индекса» означает, что он извлекает значения выбора из индекса? Попробуйте два варианта, закомментируйте idx_col1. Также переключите «col1, col2» на *. Можете ли вы поделиться, где вы получили информацию из 100 строк? –

+0

MySQL Doc говорит, что если столбец «Дополнительно», где используется индекс И с использованием индекса, это означает, что индекс используется для выполнения поиска ключевых значений (http://dev.mysql.com/doc/refman/5.5/en/explain-output .html # объяснить-Join-типов). – Marcellus

+0

Для 100 (или более) строк данных я сделал id как первичный ключ auto_increment. Затем я добавил 3 строки со случайными значениями. Чтобы умножить, я сделал что-то вроде INSERT INTO 'learning_indexes' (col1, col2, col3) SELECT CONCAT (col2, 'q'), CONCAT (col1, 'z'), CONCAT (col3, 'c') FROM' learning_indexes' ; неоднократно. Это удваивает количество строк при каждом выполнении и как-то перемешивает и изменяет вновь вставленные значения строк. – Marcellus

0

Я не могу объяснить свое дело здесь, но иногда MySQL просто выбирает «неправильный» индекс. Возможно, база данных достаточно мала, что она понимает, что в этом случае она не имеет никакого значения.

Этот запрос настолько прост, что он должен понимать, какой индекс является наиболее подходящим.

Я могу с уверенностью сказать, что когда запросы становятся более сложными, и особенно когда таблицы растут очень большими, MySQL иногда (случайный?) Решает выбрать другой индекс и пойти с этим, а затем запросы могут идти от 0,01 секунды до 100+ секунд, поэтому, если вы знаете, какой индекс является правильным, используйте FORCE INDEX(). Даже если вы используете USE INDEX(), MySQL иногда выбирает другой индекс с различным ожидаемым результатом для скорости запроса.

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