Eu tenho usado índices em meus bancos de dados MySQL por um tempo agora, mas nunca aprendi corretamente sobre eles. Geralmente, coloco um índice em todos os campos que pesquisarei ou seleciono usando umWHERE
cláusula, mas às vezes não parece tão preto e branco.
Quais são as melhores práticas para índices MySQL?
Exemplos de situações / dilemas:
Se uma tabela tiver seis colunas e todas elas forem pesquisáveis, devo indexar todas ou nenhuma?
Quais são os impactos negativos no desempenho da indexação?
Se eu tiver uma coluna VARCHAR 2500 pesquisável em partes do meu site, devo indexá-la?
mysql
indexing
query-optimization
Haroldo
fonte
fonte
Respostas:
Você definitivamente deve gastar algum tempo lendo sobre a indexação, há muito escrito sobre isso e é importante entender o que está acontecendo.
Em termos gerais, um índice impõe uma ordem nas linhas de uma tabela.
Por uma questão de simplicidade, imagine que uma tabela seja apenas um grande arquivo CSV. Sempre que uma linha é inserida, é inserida no final . Portanto, a ordem "natural" da tabela é apenas a ordem na qual as linhas foram inseridas.
Imagine que você carregou esse arquivo CSV em um aplicativo de planilha muito rudimentar. Tudo o que essa planilha faz é exibir os dados e numerar as linhas em ordem seqüencial.
Agora imagine que você precisa encontrar todas as linhas que possuem algum valor "M" na terceira coluna. Dado o que você tem disponível, você tem apenas uma opção. Você digitaliza a tabela verificando o valor da terceira coluna para cada linha. Se você tem muitas linhas, esse método (uma "verificação de tabela") pode demorar muito tempo!
Agora imagine que, além desta tabela, você tenha um índice. Esse índice específico é o índice de valores na terceira coluna. O índice lista todos os valores da terceira coluna, em alguma ordem significativa (digamos, em ordem alfabética) e, para cada um deles, fornece uma lista de números de linhas onde esse valor aparece.
Agora você tem uma boa estratégia para encontrar todas as linhas em que o valor da terceira coluna é "M". Por exemplo, você pode executar uma pesquisa binária ! Enquanto a varredura da tabela exige que você procure N linhas (onde N é o número de linhas), a pesquisa binária exige apenas que você observe as entradas do índice log-n, no pior dos casos. Uau, isso é muito mais fácil!
Obviamente, se você possui esse índice e está adicionando linhas à tabela (no final, já que é assim que nossa tabela conceitual funciona), é necessário atualizar o índice todas as vezes. Assim, você trabalha um pouco mais enquanto escreve novas linhas, mas economiza muito tempo ao procurar algo.
Portanto, em geral, a indexação cria uma troca entre eficiência de leitura e eficiência de gravação. Sem índices, as inserções podem ser muito rápidas - o mecanismo de banco de dados apenas adiciona uma linha à tabela. À medida que você adiciona índices, o mecanismo deve atualizar cada índice enquanto executa a inserção.
Por outro lado, as leituras se tornam muito mais rápidas.
Espero que isso cubra suas duas primeiras perguntas (como outras pessoas responderam - você precisa encontrar o equilíbrio certo).
Seu terceiro cenário é um pouco mais complicado. Se você estiver usando o LIKE, os mecanismos de indexação normalmente ajudarão na sua velocidade de leitura até o primeiro "%". Em outras palavras, se você estiver SELECIONANDO A coluna WHERE LIKE 'foo% bar%', o banco de dados usará o índice para encontrar todas as linhas em que a coluna começa com "foo" e precisará verificar esse conjunto de linhas intermediárias para encontrar o subconjunto que contém "bar". SELECT ... WHERE a coluna LIKE '% bar%' não pode usar o índice. Espero que você possa ver o porquê.
Por fim, você precisa começar a pensar em índices em mais de uma coluna. O conceito é o mesmo e se comporta de maneira semelhante ao material LIKE - essencialmente, se você tiver um índice em (a, b, c), o mecanismo continuará usando o índice da esquerda para a direita da melhor maneira possível. Portanto, uma pesquisa na coluna a pode usar o índice (a, b, c), como faria em (a, b). No entanto, o mecanismo precisaria fazer uma varredura completa da tabela se você estivesse pesquisando ONDE b = 5 EC = 1)
Espero que isso ajude a esclarecer um pouco, mas devo reiterar que é melhor você passar algumas horas procurando bons artigos que explicam essas coisas em profundidade. Também é uma boa ideia ler a documentação do servidor de banco de dados específico. A maneira como os índices são implementados e usados pelos planejadores de consultas pode variar bastante.
fonte
FULLTEXT
índices? Eles podem ajudar com condições comoLIKE '%bar%'
?FULLTEXT
pode ajudar com essa consulta sebar
for uma "palavra".FULLTEXT
lida com palavras, não com substrings arbitrários (comoLIKE
faz).Confira apresentações como Mais dominando a arte da indexação .
Atualização 12/2012: Publiquei uma nova apresentação minha: Como criar índices, realmente . Apresentei isso em outubro de 2012 na ZendCon em Santa Clara e em dezembro de 2012 na Percona Live London.
A criação dos melhores índices é um processo que precisa corresponder às consultas que você executa no seu aplicativo.
É difícil recomendar regras de uso geral sobre quais colunas são melhores para indexar ou se você deve indexar todas as colunas, sem colunas, quais índices devem abranger várias colunas etc. Isso depende das consultas que você precisa executar.
Sim, há alguma sobrecarga, portanto você não deve criar índices desnecessariamente. Mas você deve criar os índices que beneficiam as consultas necessárias para executar rapidamente. A sobrecarga de um índice é geralmente superada por seus benefícios.
Para uma coluna que é VARCHAR (2500), você provavelmente deseja usar um índice FULLTEXT ou um índice de prefixo:
Observe que um índice convencional não pode ajudar se você estiver procurando por palavras que possam estar no meio desse longo varchar. Para isso, use um índice de texto completo.
fonte
Não repetirei alguns dos bons conselhos em outras respostas, mas acrescentarei:
Índices compostos
Você pode criar índices compostos - um índice que inclui várias colunas. O MySQL pode usá-los da esquerda para a direita . Então, se você tem:
se você tiver um índice composto que inclua Nome / Categoria / Idade nessa ordem, essas cláusulas WHERE usariam o índice:
mas
não usaria esse índice porque tudo precisa ser usado da esquerda para a direita.
Explicar
Use Explain / Explain Extended para entender quais índices estão disponíveis para o MySQL e qual ele realmente seleciona. O MySQL usará apenas UMA chave por consulta .
Log de consulta lento
Ative o log de consultas lentas para ver quais consultas estão sendo lentas.
Colunas largas
Se você tiver uma coluna ampla em que a maior parte da distinção ocorre nos primeiros vários caracteres, poderá usar apenas os primeiros N caracteres no seu índice. Exemplo: temos uma coluna ReferenceNumber definida como varchar (255), mas 97% dos casos, o número de referência é 10 caracteres ou menos. Alterei o índice para olhar apenas os 10 primeiros caracteres e melhorou bastante o desempenho.
fonte
Você está pesquisando campo por campo ou algumas pesquisas estão usando vários campos? Quais campos estão sendo mais pesquisados? Quais são os tipos de campo? (O índice funciona melhor em INTs do que em VARCHARs, por exemplo) Você tentou usar EXPLAIN nas consultas que estão sendo executadas?
UPDATEs e INSERTs serão mais lentos. Há também os requisitos adicionais de espaço de armazenamento, mas isso não é importante nos dias de hoje.
Não, a menos que seja UNIQUE (o que significa que já está indexado) ou você só procure correspondências exatas nesse campo (sem usar a pesquisa de texto completo do LIKE ou do mySQL).
Normalmente, indexaria os campos mais consultados e, em seguida, INTs / BOOLEANs / ENUMs, em vez dos campos VARCHARS. Não se esqueça, muitas vezes você precisa criar um índice em campos combinados, em vez de um índice em um campo individual. Use EXPLAIN e verifique o log lento.
fonte
Carregar dados com eficiência : os índices aceleram as recuperações, mas reduzem a velocidade de inserções e exclusões, além de atualizações de valores nas colunas indexadas. Ou seja, os índices diminuem a maioria das operações que envolvem gravação. Isso ocorre porque a gravação de uma linha requer a gravação não apenas da linha de dados, mas também de alterações em quaisquer índices. Quanto mais índices uma tabela possui, mais alterações precisam ser feitas e maior a degradação média do desempenho. A maioria das tabelas recebe muitas leituras e poucas gravações, mas para uma tabela com uma alta porcentagem de gravações, o custo da atualização do índice pode ser significativo.
Evitar índices : se você não precisar de um índice específico para ajudar as consultas a terem um desempenho melhor, não o crie.
Espaço em disco : um índice ocupa espaço em disco e vários índices ocupam correspondentemente mais espaço. Isso pode fazer com que você atinja um limite de tamanho de tabela mais rapidamente do que se não houver índices. Evite índices sempre que possível.
Para viagem: Não exagere no índice
fonte
Em geral, os índices ajudam a acelerar a pesquisa no banco de dados, com a desvantagem de usar espaço em disco extra e reduzir a velocidade de consultas
INSERT
/UPDATE
/DELETE
. UseEXPLAIN
e leia os resultados para descobrir quando o MySQL usa seus índices.A indexação de todas as seis colunas nem sempre é a melhor prática.
(a) Você usará alguma dessas colunas ao procurar informações específicas?
(b) Qual é a seletividade dessas colunas (quantos valores distintos são armazenados, em comparação com a quantidade total de registros na tabela)?
O MySQL usa um otimizador baseado em custo, que tenta encontrar o caminho "mais barato" ao executar uma consulta. E campos com baixa seletividade não são bons candidatos.
Já respondeu: espaço em disco extra, desempenho inferior durante a inserção - atualização - exclusão.
Experimente o Índice FULLTEXT .
fonte
1/2) Os índices aceleram certas operações de seleção, mas desaceleram outras operações, como inserir, atualizar e excluir. Pode ser um bom equilíbrio.
3) use um índice de texto completo ou talvez esfinge
fonte
slow down other operations like insert, update and deletes
você possa usar oSTART TRANSACTION;
YOUR CODE HERE;
COMMIT
What pode ajudar a evitarslowing down
as outras operações, pois ele só verifica uma das restrições uma vez. CAVEAT: Se você usarREPLACE INTO
e seuSQL_MODE
<>STRICT_ALL_TABLES
OUTRADITIONAL
OBulk Load
ignorará a substituição e inserirá duplicatas.