A chave que são duas colunas
Uma chave primária composta é uma chave primária feita de mais de uma coluna. O Rails usa um id autoincremental como padrão há tanto tempo que a alternativa parece exótica. Mas, em algumas tabelas, a identidade de uma linha é mesmo um par de valores, e fingir o contrário tem um custo.
O padrão de tabela de junção
Esta aplicação tem dez tabelas com o mesmo formato: enrollments, lesson_completions, lesson_notes, bookmarks, user_badges, solution_reveals, partner_course_sponsorships, identity_authentications, experience_points e partner_handoff_nonces.
Cada uma tem um id substituto e um índice único sobre as colunas que a identificam. Em todos os casos é um par:
t.index [ "user_id", "lesson_id" ],
name: "index_lesson_completions_on_user_id_and_lesson_id",
unique: true
A coluna id nunca responde a uma pergunta que alguém faça. Ninguém procura a conclusão 4.812. As pessoas perguntam se este usuário concluiu esta lição, e é o índice único que responde isso.
O que a chave substituta custa
Ela custa oito bytes por linha para a coluna, mais um índice sobre ela que nada consulta: o índice de chave primária que o Postgres constrói automaticamente.
Com 2519 lições e as conclusões registradas nelas, isso não é nada. Numa tabela de cem milhões de linhas, são gigabytes de índice existindo para satisfazer uma convenção.
flowchart TB
T["lesson_completions"] --> I["id: bigint, chave primária"]
T --> U["user_id"]
T --> L["lesson_id"]
I --> X["indexado, nunca consultado"]
U --> Y["índice único sobre o par"]
L --> Y
Y --> Z["esta é a identidade real"]
O que ela compra
Ela compra um identificador estável de uma coluna só. URLs, chaves estrangeiras de outras tabelas e a própria maquinaria do Active Record ficam mais simples quando a identidade é um valor.
DELETE FROM lesson_completions WHERE id = $1 não deixa dúvida, enquanto a versão composta precisa dos dois valores em todo lugar.
E é o que toda ferramenta do Rails espera. find, update, destroy, os helpers de formulário e o dom_id foram todos escritos pressupondo uma coluna.
A posição honesta
A chave substituta costuma estar certa, e está certa aqui. Esta aplicação não deveria adotar chaves compostas, e não é por isso que vale aprendê-las.
Algumas tabelas que você vai encontrar por aí já as têm: esquemas legados, tabelas particionadas, tabelas com sharding, qualquer coisa em que um id de inquilino faça parte de toda chave. O Rails 7.1 ganhou suporte real a elas, o que mudou o que é possível.
Conhecer a troca permite reconhecer as tabelas em que o padrão está errado. Esse conjunto é menor do que os entusiastas dizem, e maior do que "nunca".
Pontos-chave
- Uma chave primária composta é uma chave primária feita de mais de uma coluna.
- Esta aplicação tem dez tabelas de junção com um
idsubstituto e um índice único na identidade real. - A chave substituta custa oito bytes por linha e um índice que nada consulta.
- Ela compra um identificador estável de uma coluna e compatibilidade com toda ferramenta do Rails.
- Aprenda chaves compostas para reconhecer as tabelas em que o padrão está errado, não para converter estas.
Continue com a aula 2
Quando a chave precisa ser composta
Mostra por que tabelas particionadas, dados com sharding e esquemas legados exigem chave composta, e a unicidade sozinha não.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.