Digamos que eu tenha uma relação de um-para-N (person_id, pet_id)
. Eu tenho uma tabela onde pet_id
é a chave primária.
Entendo que um índice secundário do InnoDB é essencialmente uma árvore B, onde os valores são os valores da chave primária correspondentes para a linha.
Agora, suponha que uma pessoa possa ter milhares de animais de estimação e eu geralmente quero os animais de estimação em ordem de pet_id
. Então seria importante se os registros no índice secundário forem classificados por (person_id, pet_id)
ou apenas person_id
com os pet_id
para que person_id
não sejam classificados. Adivinhando o mais tarde.
Então, se person_id
não for único, os registros são classificados fisicamente por (person_id, pet_id)
ou APENAS pet_id
?
obrigado
mysql
innodb
primary-key
clustered-index
user3391564
fonte
fonte
person_id
não for único, os registros são classificados fisicamente por(person_id, pet_id)
ou APENASperson_id
?"Respostas:
Não. Se sua tabela possui o mecanismo InnoDB e o
PRIMARY KEY
é(pet_id)
, definir um índice secundário como(person_id)
ou(person_id, pet_id)
não faz diferença.O índice também inclui a
pet_id
coluna, para que os valores sejam classificados como(person_id, pet_id)
nos dois casos.Uma consulta como a sua:
precisará acessar apenas o índice para obter os valores e, mais ainda, não precisará fazer nenhuma classificação, pois os
pet_id
valores já estão classificados no índice. Você pode verificar isso observando os planos de execução (EXPLAIN
):Primeiro, tentamos com uma tabela MyISAM:
Observe a lista de arquivos!
Agora, MyISAM com índice composto:
O filesort se foi , conforme o esperado.
Agora vamos tentar o mesmo com o mecanismo InnoDB:
Nenhum arquivo sort também! Mesmo que o índice não tenha explicitamente a
pet_id
coluna, os valores estão lá e classificados. Você pode verificar se, se definir o índice com(person_id, pet_id)
, oEXPLAIN
é idêntico.Vamos realmente fazer isso, com o InnoDB e o índice composto:
Planos idênticos ao caso anterior.
Para ter 100% de certeza, também executo os dois últimos casos (mecanismo InnoDB, com índices único e composto), permitindo a
file_per_table
configuração e adicionando alguns milhares de linhas na tabela:Nos dois casos, a verificação do tamanho real do arquivo gera resultados idênticos :
fonte
(<some_column>)
e(<some_column>, <pk>)
porqueON (<some_column>)
é equivalente aON (<some_column>) INCLUDE (<pk>)
e nãoON (<some_column>, <pk>)
. Na maioria das circunstâncias, isso tem um significado praticamente nulo, mas se sua PK for aleatória (ou seja, um UUID),ON (<s_c>,<pk>)
poderá levar a uma fragmentação extra ou se sua PK for significativa além de ser uma chave e você poderáORDER BY s_c, pk
ser mais rápido com o índice. já está totalmente em ordem.INCLUDE (columns)
funcionalidade. Essa é outra razão pela qual concluí que o(s_c)
índice é equivalente(s_c, pk)
.De acordo com a documentação do MySQL sobre os índices agrupados e secundários
Portanto, adicionar a PRIMARY KEY a um índice secundário é definitivamente redundante. Sua entrada de índice gostaria
(person_id, pet_id, pet_id)
. Isso também iria inchar desnecessariamente o índice secundário por ter 2 cópias doPRIMARY KEY
.Para o índice com
(person_id)
, se você executasse uma consulta como estaO
PRIMARY KEY
estaria totalmente envolvido nessa consulta e produzirá os resultados ordenados dePRIMARY KEY
qualquer maneira. Do ponto de vista físico, as linhas são ordenadas por ordem de inserção. Se o pet_id for AUTO_INCREMENT, será pedido pelo número automático.fonte
(owner_id, pet_id)
mas poderá criar uma chave(vet_id, pet_id[, owner_id])
para utilizar ordem de coluna diferente.Dica 1:
é perfeitamente válido. Tem a vantagem de desempenho de ser mais eficiente quando muitas consultas precisam encontrar várias linhas
WHERE x = 123
. Ou seja, é um pouco mais eficiente que o "óbvio"A única regra sobre
AUTO_INCREMENT
(para o InnoDB) é queid
deve ser a primeira coluna em algum índice. Observe que essa regra não diz nada sobrePRIMARY
ouUNIQUE
ou 'apenas coluna'.A dica é útil para mesas enormes que geralmente são buscadas
x
junto com outras coisas.Dica 2: suponha que você tenha
Este é um índice de "cobertura":
Ou seja, toda a consulta pode ser feita dentro do BTree do índice. O EXPLAIN dirá "Usando o índice".
fonte