Saída EXPLAIN sugere que meu índice não está sendo usado

9

Eu configurei minha tabela com um índice apenas em done_status (done_status = INT):

insira a descrição da imagem aqui

Quando eu uso:

EXPLAIN SELECT * FROM reminder  WHERE done_status=2

Eu recebo de volta:

id select_type tipo de tabela possible_keys key key_len ref linhas Extra
1 lembrete SIMPLES TUDO done_status NULL NULL NULL 5 Usando where

Mas quando eu emito este comando:

EXPLAIN SELECT * FROM reminder  WHERE done_status=1

Eu recebo o seguinte retornado:

id select_type tipo de tabela possible_keys key key_len ref linhas Extra
1 lembrete SIM ref referência done_status done_status 4 const 2   

O EXPLAINme mostra que ele usa 5 linhas, a segunda vez 2 linhas.

Eu não acho que o índice é usado, se eu entendi direito na primeira vez, ele deve me dar três linhas. O que eu faço de errado?

SHOW INDEX FROM reminder:

Tabela Nome-chave não exclusivo Seq_in_index Nome_da_coluna Cardinalidade do agrupamento Sub_parta Nulo compactado Índice_tipo Comentário Index_comment
lembrete 1 done_status 1 done_status A 5 NULL NULL BTREE

explicar estendido:

id select_type tipo de tabela possible_keys key key_len ref linhas filtradas Extra
1 lembrete SIM ref referência done_status done_status 4 const 2 100,00

show warnings não mostrou nada de interesse.

TasostheGreat
fonte
Confie em mim, o índice funciona. Mas eu não posso ver nada facilmente em sua tela tiro - você pode fazer um "índice de programa de YourTable"
sim editado minha pergunta
utilize o Glorifica \ G para o esquema e explicar resultado plano, que deve ser mais legível
ajreal
Fora de interesse que você pode repetir com um "explicar estendida" e um "show advertências" que vai mostrar os escolhe SQL mysql reais
@ajreal o que é glorificar?

Respostas:

4

Você entende mal o que é o campo 'linhas'. É o número de linhas que o mysql calcula que ele precisará ler para satisfazer sua consulta. Este valor pode ser bastante impreciso. Isso não significa que este é o número de linhas no resultado - ou o número real de linhas lidas pelo mysql


fonte
Assim? Onde eu disse que sim? O que o otimizador escolhe depende dele? O índice ainda funciona.
@ajreal Mas isso não significa que o índice esteja quebrado. Apenas o otimizador escolhe (em sua mente) a maneira mais eficiente de consultar os dados. Presumi que o OP esperava que a coluna de linhas no EXPLAIN fosse exata. Isso não significa que o índice está quebrado - apenas que o mysql escolhe não usá-lo (provavelmente).
11
@ajreal: Estou faltando algo nos seus pontos. A coluna de linhas de uma explicação não tem nada a ver com índices, certo? O Mysql escolhe não usar o índice (talvez todos os dados estejam em uma única página). Não tem certeza de que estou entendendo o seu ponto? A otimização de consulta em uma tabela de 5 linhas produzirá alguns resultados "ímpares" porque praticamente não importa como você otimizar.
Nesse caso, quem se importa com o índice que o otimizador escolhe? Não há nada de errado com o próprio índice, porque o otimizador sentiu que não precisava dele - o que importa?
3

O primeiro plano de execução não utiliza o índice com certeza,
pode ser que o information_schema.statistics no índice não alcance os dados após algumas operações de gravação ou a tabela não seja acessada por um longo período de tempo.

como explicado aqui: - De onde o MySQL Query Optimizer lê as estatísticas do índice?

para o segundo plano de execução, parece que o information_schema.statistics já atualiza e corrige o problema de cardinalidade NULL.

Portanto, é executar a consulta de acordo com o otimizador de índice.

Para tabela com pequenas linhas, isso não importa muito.
Mas os dados crescerão, o desenvolvedor deve sempre verificar isso
e executar a tabela de análise necessária quando a cardinalidade do encontro for nula no índice.

ajreal
fonte
0

O primeiro plano de execução não está usando um índice.

Do site de referência do MySQL :

Às vezes, o MySQL não usa um índice, mesmo que esteja disponível. Uma circunstância em que isso ocorre é quando o otimizador estima que o uso do índice exigiria que o MySQL acessasse uma porcentagem muito grande de linhas na tabela. (Nesse caso, é provável que uma varredura de tabela seja muito mais rápida porque requer menos buscas.) No entanto, se essa consulta usar LIMIT para recuperar apenas algumas das linhas, o MySQL usará um índice de qualquer maneira, porque poderá encontrar muito mais rapidamente as poucas linhas para retornar no resultado.

Se sua tabela possui apenas 5 linhas e sua consulta seleciona 3 delas, o otimizador do MySQL assume que é mais eficiente verificar a tabela inteira.

Matthew Sammut
fonte