Dois índices de coluna única vs um índice de duas colunas no MySQL?

114

Estou enfrentando o seguinte e não tenho certeza de quais são as melhores práticas.

Considere a seguinte tabela (que ficará grande):

id PK | giver_id FK | destinatário_id FK | encontro

Estou usando o InnoDB e, pelo que entendi, ele cria índices automaticamente para as duas colunas de chave estrangeira. No entanto, também farei muitas consultas em que preciso encontrar uma combinação específica de:

SELECT...WHERE giver_id = x AND recipient_id = t.

Cada uma dessas combinações será única na tabela.

Há algum benefício em adicionar um índice de duas colunas sobre essas colunas ou os dois índices individuais, em teoria, seriam suficientes / iguais?

Tom
fonte
1
Se a combinação das duas colunas for única, você pode criar um índice de duas colunas com um recurso exclusivo que não apenas aumentará a velocidade de sua consulta, mas também adicionará consistência à sua tabela.
sguven
"O MySQL pode usar índices de várias colunas para consultas que testam todas as colunas do índice ou consultas que testam apenas a primeira coluna, as duas primeiras colunas, as três primeiras colunas e assim por diante. Se você especificar as colunas à direita ordem na definição do índice, um único índice composto pode acelerar vários tipos de consultas na mesma tabela. " - Índices de múltiplas colunas
AlikElzin-kilaka,
Para extrapolar em @ user1585784; Se a combinação das duas colunas for única, acho que se deve usar uma chave exclusiva para elas. Na verdade, se alguém deseja impor a exclusividade no nível do banco de dados, uma chave exclusiva é a maneira mais fácil de fazer ...
Erk

Respostas:

133

Se você tiver dois índices de coluna única, apenas um deles será usado em seu exemplo.

Se você tiver um índice com duas colunas, a consulta pode ser mais rápida (você deve medir). Um índice de duas colunas também pode ser usado como um índice de coluna única, mas apenas para a coluna listada primeiro.

Às vezes, pode ser útil ter um índice em (A, B) e outro índice em (B). Isso torna as consultas usando uma ou ambas as colunas mais rápidas, mas é claro que também usa mais espaço em disco.

Ao escolher os índices, você também precisa considerar o efeito na inserção, exclusão e atualização. Mais índices = atualizações mais lentas.

Mark Byers
fonte
1
"O MySQL pode usar índices de várias colunas para consultas que testam todas as colunas do índice ou consultas que testam apenas a primeira coluna, as duas primeiras colunas, as três primeiras colunas e assim por diante. Se você especificar as colunas à direita ordem na definição do índice, um único índice composto pode acelerar vários tipos de consultas na mesma tabela. " - Índices de múltiplas colunas
AlikElzin-kilaka,
33

Um índice de cobertura como:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... significaria que o índice poderia ser usado se uma consulta fosse referida giver_idou uma combinação de giver_ide recipient_id. Lembre-se de que os critérios de índice são baseados na extrema esquerda - uma consulta referente a apenas recipient_idnão seria capaz de usar o índice de cobertura na instrução que forneci.

Além disso, o MySQL pode usar apenas um índice por SELECT, portanto, um índice de cobertura seria o melhor meio de otimizar suas consultas.

Pôneis OMG
fonte
10
MySQL can only use one index per SELECTisso não é mais verdade, seria bom se você editasse sua resposta para ser atualizada.
Davor,
Você se importaria de explicar por que o índice de cobertura não poderia ser usado por recipient_id?
Ivo Pereira
2
@IvoPereira Índices de colunas múltiplas no MySQL permitem que você use todos os campos no índice da esquerda para a direita. Por exemplo, se você tiver um INDEX (col1, col2, col3, col4), o índice será aplicado para pesquisas com uma WHEREcláusula como col1 = 'A'ou col1 = 'A' AND col2 = 'B'ou col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D', mas este índice específico não será usado para nada como WHERE col2 = 'B'ou WHERE col3 = 'C' AND col4 = 'D'porque os campos de pesquisa não são deixados na maior parte na definição do índice. Você teria que adicionar índices adicionais para cobrir esses campos.
Slicktrick de
"um índice por SELECT" , isso ainda é verdade para o mariadb 10.1?
oldboy
1
@Anthony: Não. Veja o comentário de Davor acima.
kapad de
4

Se um dos índices de chave estrangeira já for muito seletivo, o mecanismo de banco de dados deve usar aquele para a consulta que você especificou. A maioria dos mecanismos de banco de dados usa algum tipo de heurística para escolher o índice ideal nessa situação. Se nenhum índice for altamente seletivo por si só, provavelmente faz sentido adicionar o índice construído em ambas as chaves, pois você diz que usará muito esse tipo de consulta.

Outra coisa a considerar é se você pode eliminar o campo PK nesta tabela e definir o índice de chave primária nos campos giver_ide recipient_id. Você disse que a combinação é única, então possivelmente funcionaria (dadas muitas outras condições que só você pode responder). Normalmente, porém, acho que a complexidade adicionada não compensa o incômodo.

Mark Wilkins
fonte
Obrigado Mark, uma das teclas é realmente muito seletiva, então deve funcionar. Optei por manter os dois índices (automáticos) no lugar e ver como eles funcionam ao longo do tempo. Também pensei em uma combinação doador: chave primária do destinatário, mas como cada campo também precisa ser pesquisável individualmente, isso apenas adicionaria sobrecarga de php. Além disso, a nova chave seria uma string (mais longa) em vez de um inteiro (mais curto).
Tom
2

Outra coisa a considerar é que as características de desempenho de ambas as abordagens serão baseadas no tamanho e na cardinalidade do conjunto de dados. Você pode descobrir que o índice de 2 colunas só percebe mais desempenho em um determinado limite de tamanho do conjunto de dados ou exatamente o oposto. Nada pode substituir as métricas de desempenho para o seu cenário exato.

Andrew
fonte
você poderia criar um link para alguma documentação sobre isso. Obrigado.
kapad de