O ponto essencial é que o índice não pode ser usado se o banco de dados tiver que fazer uma conversão no lado da tabela da comparação.
Além disso, o banco de dados sempre encobre Strings -> Numbers porque esta é a maneira determinística (caso contrário, 1 poderia ser convertido em '01', '001' conforme mencionado nos comentários).
Então, se compararmos os dois casos que parecem confundi-lo:
-- index is used
EXPLAIN SELECT * FROM a_table WHERE int_column = '1';
O banco de dados converte a string '1' para o número 1 e então executa a consulta. Ele finalmente tem int em ambos os lados para que possa usar o índice.
-- index is NOT used. WTF?
EXPLAIN SELECT * FROM a_table WHERE str_column = 1;
Novamente, ele converte a string em números. No entanto, desta vez ele precisa converter os dados armazenados na tabela. Na verdade, você está realizando uma pesquisa como
cast(str_column as int) = 1
. Isso significa que você não está mais pesquisando nos dados indexados, o banco de dados não pode usar o índice. Por favor, dê uma olhada nisso para mais detalhes:
- http://use-the- index-luke.com/sql/where-clause/obfuscation/numeric-strings
- http://use- the-index-luke.com/sql/where-clause/functions/case-insensitive-search