A primeira coisa que você deve saber é que os índices são uma maneira de evitar a varredura da tabela completa para obter o resultado que você está procurando.
Existem diferentes tipos de índices e eles são implementados na camada de armazenamento, portanto não há um padrão entre eles e eles também dependem do mecanismo de armazenamento que você está usando.
InnoDB e o índice B + Tree
Para o InnoDB, o tipo de índice mais comum é o índice baseado em Árvore B +, que armazena os elementos em uma ordem classificada. Além disso, você não precisa acessar a tabela real para obter os valores indexados, o que torna sua consulta muito mais rápida.
O "problema" sobre esse tipo de índice é que você precisa consultar o valor mais à esquerda para usar o índice. Portanto, se seu índice tiver duas colunas, por exemplo, last_name e first_name, a ordem em que você consulta esses campos é muito importante .
Portanto, dada a seguinte tabela:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Esta consulta tiraria proveito do índice:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Mas o seguinte não
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Porque você está consultando a first_name
coluna primeiro e ela não é a coluna mais à esquerda no índice.
Este último exemplo é ainda pior:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Porque agora, você está comparando a parte mais à direita do campo mais à direita no índice.
O índice de hash
Esse é um tipo de índice diferente que, infelizmente, apenas o back-end de memória suporta. É extremamente rápido, mas útil apenas para pesquisas completas, o que significa que você não pode usá-lo para operações como >
, <
ou LIKE
.
Como ele funciona apenas para o back-end de memória, você provavelmente não o utilizará com muita frequência. O principal caso em que posso pensar agora é aquele em que você cria uma tabela temporária na memória com um conjunto de resultados de outra seleção e executa várias outras seleções nessa tabela temporária usando índices de hash.
Se você tiver um VARCHAR
campo grande , poderá "emular" o uso de um índice de hash ao usar uma Árvore B, criando outra coluna e salvando um hash do grande valor nela. Digamos que você esteja armazenando um URL em um campo e os valores sejam bastante grandes. Você também pode criar um campo inteiro chamado url_hash
e usar uma função hash como CRC32
ou qualquer outra função hash para fazer o hash do URL ao inseri-lo. E então, quando você precisar consultar esse valor, poderá fazer algo assim:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
O problema com o exemplo acima é que, como a CRC32
função gera um hash bem pequeno, você terá muitas colisões nos valores do hash. Se você precisar de valores exatos, poderá corrigir esse problema da seguinte maneira:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Ainda vale a pena fazer hash, mesmo que o número de colisão seja alto, porque você só fará a segunda comparação (a string 1) com os hashes repetidos.
Infelizmente, usando essa técnica, você ainda precisa acertar a tabela para comparar o url
campo.
Embrulhar
Alguns fatos que você pode considerar sempre que quiser falar sobre otimização:
A comparação inteira é muito mais rápida que a comparação de strings. Pode ser ilustrado com o exemplo sobre a emulação do índice de hash em InnoDB
.
Talvez, adicionar etapas adicionais em um processo o torne mais rápido, e não mais lento. Isso pode ser ilustrado pelo fato de que você pode otimizar um SELECT
dividindo-o em duas etapas, fazendo com que o primeiro armazene valores em uma tabela de memória criada recentemente e execute as consultas mais pesadas nessa segunda tabela.
O MySQL também possui outros índices, mas acho que o B + Tree é o mais usado já e o hash é uma coisa boa a saber, mas você pode encontrar os outros na documentação do MySQL .
Eu recomendo que você leia o livro "High Performance MySQL", a resposta acima foi definitivamente baseada em seu capítulo sobre índices.