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?


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.


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.


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.


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.


você poderia criar um link para alguma documentação sobre isso. Obrigado.
— kapad de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.