Suponha que eu tenha uma consulta como:
SELECT *
FROM table_a
JOIN table_b USING (id)
WHERE table_b.column = 1
Eu tenho um índice ativado id
e um índice ativado, column
mas geralmente adiciono um índice composto com ambos, o que pode melhorar a eficiência de consultas como essa. Minha pergunta é sobre a ordem das colunas no índice. Por tentativa e erro, descobri que às vezes o DBMS prefere o índice unido primeiro e às vezes prefere o WHERE
índice primeiro.
Na consulta acima, existe uma regra rígida e rápida que eu possa seguir para saber qual ordem de chave funcionará melhor?
Normalmente, apenas adiciono os dois índices, executo EXPLAIN
a consulta e verifico qual é o preferido, depois removo o outro. Mas esse processo parece que pode ser melhorado por uma melhor compreensão da lógica envolvida na determinação da ordem do índice.
Para esta consulta
A maneira ideal é executá-lo é
WHERE
cláusula fornece alguma filtragem, então vamos fazer uso dela. Ou seja, tenha um índicetable_b
começando comcolumn
. (Mais tarde, discutiremos se devemos torná-lo composto.) Assim, o Otimizador usará esse índice para encontrar linha(s) detable_b
.JOIN
paratable_a
. (Observe queJOIN
, notLEFT JOIN
está sendo usado;LEFT JOIN
é uma história diferente.)table_a
, é necessário um índice começando comid
. (Nota:USING(id)
significatable_a.id = table_b.id
.)Até agora, temos
Cobertura?
Não sabemos quais outras colunas existem nas duas tabelas. Se houver muito poucas colunas, pode ser tentador criar um índice de "cobertura". Este é um índice que contém todas as colunas necessárias em qualquer lugar do arquivo
SELECT
. O benefício é alguma aceleração de desempenho ao olhar apenas no BTree do índice e não ter que tocar no BTree de dados.Pois
table_b
, seria tentador dizerINDEX(column, id)
. Isso seria bom (e 'cobrindo') se houvesse apenas essas duas colunas. Mas provavelmente há mais colunas. Então, provavelmenteINDEX(column)
é tudo o que vale a pena fazer.Para
table_a
, suponho queid
seja oPRIMARY KEY
(que é, por definição, único e um índice). Então, nada mais é necessário lá.Bottom line : Use os dois índices de coluna única listados acima.
E este exemplo não exemplifica nada sobre índices "compostos". Para saber mais sobre isso, veja
Cardinalidade e intervalo
Cardinalidade e índice composto
de uma coluna Livro de
receitas de indexação
Melhor exemplo
Como eu disse, seu exemplo não exemplifica a pergunta. Então, vou tentar responder "Quando devo usar um índice composto"? Existem muitos casos (veja os links); Vou lhe dar um caso simples.
As características relevantes são:
x
ey
estão na mesma tabela. (Não é possível criar um índice em duas tabelas.)AND
é usado. (OR
não pode ser otimizado.)=
. (Composto não ajudará se ambos forem intervalos.)y
é um "intervalo" (exemplos:y>2
,y LIKE 'm%'
,y BETWEEN ... AND ...
).A regra geral é :
=
colunas primeiro (x
no meu exemplo)y
)Ou seja, você deve encomendá-lo
INDEX(x,y)
.Para
WHERE x = 1 AND y = 2
(ambos=
), não importa se você temINDEX(x,y)
ouINDEX(y,x)
.Outro detalhe : Com
ENGINE=InnoDB
, asPRIMARY KEY
colunas são implicitamente anexadas a cada chave secundária. Portanto, seuINDEX(column)
é o mesmo queINDEX(column, id)
. Mas este fato não desempenha um papel nesta discussão.Percebo que estou discordando de outras respostas aqui (e em outros lugares), mas mantenho minha posição.
Uma boa regra geral é tornar a coluna inicial em um índice composto o mais seletivo possível. Uma boa maneira de imaginar isso é com a analogia da lista telefônica: imagine que você precisa encontrar alguém na lista telefônica e há dois índices... o primeiro é Sobrenome, Nome. O segundo é FirstName, LastName. Qual índice você usaria para encontrar alguém chamado John Xilofone? Certamente você usaria o índice LastName, Firstname, pois há muito poucas entradas de Xilofone e levará muito menos tempo do que procurar em todas as entradas de John uma com o sobrenome de Xilofone.
Portanto, se
id
for altamente seletivo ecolumn
tiver baixa seletividade, você deseja que o índice seja(id, column)
, mas secolumn
tiver alta seletividade eid
baixa seletividade, provavelmente se beneficiará de ter o índice definido como(column, id)
.Você pode ver um índice
(column, id)
sendo usado se estiver unindo duas tabelas quando resultarid
em um número substancialmente reduzido de linhas que precisam ser unidas.where column = x
x
No exemplo que você deu, sua melhor aposta é não ter um índice composto se você estiver livre para alterar a ordem de junção:
db<>fique aqui