Eu li vários artigos sobre eficiência de chaves primárias, dependendo do mecanismo de armazenamento, e estou confuso.
Dada uma tabela muitos-para-muitos simples com dois campos storeId
e zoneId
, qual dos seguintes designs é o mais eficiente com o InnoDB e por quê?
- usando os dois campos como uma chave primária composta:
CREATE TABLE store_zone(
storeId INT(10) UNSIGNED NOT NULL,
zoneId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY(storeId, zoneId)
);
- Usando uma chave primária específica de incremento automático:
CREATE TABLE store_zone(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
storeId INT(10) UNSIGNED NOT NULL,
zoneId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY(id),
UNIQUE KEY(storeId, zoneId)
);
Notas:
- Eu preciso de uma chave única no par (
storeId
, ) de qualquer maneirazoneId
- Eu tenho chaves estrangeiras para as tabelas
store
ezone
, não mostradas aqui para facilitar a leitura , portanto, em ambos os casos, há um índice extra necessáriozoneId
também
Análise
Já que estamos falando do InnoDB, vamos nos concentrar no
gen_clust_index
. É um índice especial que mantém a PRIMARY KEY e os dados de linha associados acessíveis nas mesmas páginas do InnoDB.De acordo com a documentação do MySQL no gen_clust_index
Sendo assim, você realmente sentiria eficiência ou deficiência nas seguintes áreas:
Espaço em disco
Ter a única coluna auto_increment como
PRIMARY KEY
mantém o tamanho geral da PRIMARY KEY menor do que ter duas colunas. Por quê? As páginas BTREE seriam duas vezes maiores sePRIMARY KEY
fossem dois INTs em vez de um. Isso se torna ainda mais doloroso se você usar restrições de chave estrangeira e índices secundários, pois eles devem aumentar de tamanho também.Nesse caso, você escolheria o segundo esquema para melhor uso do índice.
Inserir desempenho
Inserir dados de linha em uma tabela InnoDB que possui dois índices UNIQUE exige o dobro de gerenciamento de BTREE e verificações exclusivas.
(storeId, zoneId)
)Microssegundos adicionais para cada índice UNIQUE adicional seriam somados no tempo de CPU ao inserir milhões de linhas.
Nesse caso, você escolheria o primeiro esquema para INSERTs mais rápidos.
Conclusão
O espaço em disco e os problemas de desempenho de inserção praticamente o forçam a escolher. Obviamente, você escolhe com qual viver. Se você usar restrições de chave estrangeira que representam
(storeId, zoneId)
, precisará do segundo esquema usando o auto_increment como referência em tabelas externas.