fundo
Eu tenho essas tabelas
+-------------------------+ +------------------------+
|Airport | |Country |
|-------------------------| |------------------------|
|airport_code string (PK) | |country_code string (PK)|
|address string | |name string |
|name string | +------------------------+
+-------------------------+
+-------------------------+
|Currency |
|-------------------------|
|currency_code string (PK)|
|name string |
+-------------------------+
airport_code é o código de aeroporto IATA (International Air Transport Association) , você pode vê-los em suas etiquetas de bagagem quando viaja de avião.
country_code é o código de país padrão ISO 3166-1 A3 , você pode vê-los nos Jogos Olímpicos.
currency_code é o código de moeda IS0 417 padrão de 3 caracteres , você pode vê-los em painéis de exibição de câmbios internacionais.
Questões
Essas PKs naturais são boas o suficiente?
O uso de padrões respeitados no mundo, aceitos por indústrias inteiras, é bom o suficiente para PKs?
Essas tabelas precisam de substitutos, não importa o quê?
fonte
Eu acho que necessidade é uma palavra muito forte e, em sentido estrito, as tabelas provavelmente não precisam de chaves substitutas .
No entanto, se fosse meu banco de dados, provavelmente adicionaria chaves substitutas de qualquer maneira. Talvez eu não queira necessariamente que meu design de banco de dados dependa de vários terceiros (IATA, ISO), independentemente de quão estáveis sejam seus padrões. Ou talvez eu não queira depender de um padrão específico (existem outros padrões de código de moeda? Não sei). Eu provavelmente modelaria minhas tabelas com chaves substitutas da seguinte forma:
Em outras palavras, a menos que esses códigos padrão da indústria sejam inerentemente importantes para o meu aplicativo, eu não os usaria como o PK das minhas tabelas. Eles são apenas rótulos. A maioria das minhas outras tabelas provavelmente terá chaves substitutas de qualquer maneira, e essa configuração adicionaria consistência ao meu modelo de dados. O custo de 'adicionar' as chaves substitutas é mínimo.
Atualização baseada em alguns dos comentários:
Sem conhecer o contexto das tabelas de exemplo, é impossível saber o quão importantes são os códigos de aeroporto IATA para o aplicativo usando o banco de dados. Obviamente, se os códigos IATA são de importância central e usados de maneira generalizada em todo o aplicativo, pode ser a decisão correta, após análise adequada, usar os códigos como PK da tabela.
No entanto, se a tabela for apenas uma tabela de pesquisa usada em alguns cantos do aplicativo, a importância relativa dos códigos IATA pode não justificar um ponto tão proeminente na infraestrutura do banco de dados. Claro, talvez você precise fazer uma junção adicional em algumas consultas aqui e ali, mas esse esforço pode ser trivial em comparação com o esforço necessário para fazer a pesquisa para garantir que você compreenda completamente as implicações de tornar os códigos IATA os campo de chave primária. Em alguns casos, não só eu não ligo, mas não quero ter que me importar com os códigos IATA. O comentário de @James Snell abaixo é um exemplo perfeito de algo que talvez eu não queira se preocupar em afetar o PK das minhas tabelas.
Além disso, a consistência no design é importante. Se você possui um banco de dados com dezenas de tabelas que projetam consistentemente chaves substitutas e algumas tabelas de pesquisa que usam códigos de terceiros como PK, isso introduz uma inconsistência. Isso não é totalmente ruim, mas requer atenção extra na documentação e em outras que possam não ser justificadas. Eles são tabelas de pesquisa por amor de Deus, basta usar uma chave substituta para garantir a consistência.
Atualização baseada em pesquisas adicionais:
Ok, a curiosidade me mordeu e decidi fazer uma pesquisa sobre os códigos do aeroporto da IATA por diversão, começando pelos links fornecidos na pergunta.
Como se vê, os códigos IATA não são tão universais e autoritários quanto a pergunta os torna. De acordo com esta página :
Além disso, os códigos IATA e ICAO são diferentes dos códigos de identificação FAA , que são outra maneira de identificar os aeroportos.
Meu ponto de vista é não iniciar um debate sobre quais códigos são melhores ou mais universais ou mais autoritativos ou mais abrangentes, mas mostrar exatamente por que projetar sua estrutura de banco de dados em torno de um identificador de terceiros arbitrário não é algo que eu escolheria fazer , a menos que haja um motivo comercial específico para fazer isso .
Nesse caso, acho que meu banco de dados ficaria melhor estruturado, mais estável e mais flexível, renunciando aos códigos IATA (ou qualquer código potencialmente alterável de terceiros) como candidato à chave primária e usando uma chave substituta. Ao fazer isso, posso renunciar a possíveis armadilhas que possam surgir devido à seleção da chave primária.
fonte
select * from baggage where airport_code = 'LHR'
, o que significa que o banco de dados é apenas utilizável na aplicação, que é muito estreita e proprietária. abordagem, especialmente quando o proprietário da empresa é quem pagou pelo banco de dados e, portanto, o possui. Além disso, você precisará escrever um código para fazer coisas comuns, como importar dados de um banco de dados para outro, para evitar colisões de PK.Embora ter chaves substitutas nos campos seja bom, não há nada de errado em que algo a considerar possa ser o próprio tamanho da página de índice.
Como esse é um banco de dados relacional, você fará muitas junções e ter uma chave substituta de um tipo numérico pode facilitar o manuseio no banco de dados, ou seja, o tamanho da página de índice será menor e, portanto, mais rápido na pesquisa. Se este for um projeto pequeno, isso não importará e você se sairá sem problemas; no entanto, quanto maior o aplicativo, mais você reduzirá os gargalos.
Ter um BIGINT, INT, SMALLINT, TINYINT ou qualquer outro tipo de dados do tipo inteiro pode poupar alguns problemas no futuro.
Apenas meus 2 centavos
ATUALIZAR:
Projeto pequeno - usado por algumas, talvez até algumas dezenas de pessoas. Em pequena escala, projeto de demonstração, projeto para uso pessoal, algo a ser adicionado a um portfólio ao apresentar suas habilidades sem experiência e similares.
Grande projeto - usado por milhares, dezenas de milhares, milhões de usuários diariamente. Algo que você criaria para uma empresa nacional / internacional com uma enorme base de usuários.
Geralmente, o que acontece é que alguns dos registros são selecionados com frequência e o servidor armazena em cache os resultados para acesso rápido, mas de vez em quando você precisa acessar algum registro menos usado, momento em que o servidor precisaria mergulhar no índice página. (no exemplo acima, com os nomes dos aeroportos, as pessoas costumam voar em companhias aéreas domésticas, como Chichago -> Los Angeles, mas com que frequência as pessoas voam de Boston -> Zimbábue)
Se VARCHAR for usado, isso significa que o espaçamento não é uniforme, a menos que os dados sejam sempre do mesmo comprimento (nesse ponto, um valor CHAR é mais eficaz). Isso torna a pesquisa no índice mais lenta e, como o servidor já está ocupado processando milhares e milhares de consultas por segundo, agora é preciso perder tempo passando por um índice não uniforme e fazer o mesmo novamente nas junções (que é mais lento do que Para selecionar regularmente em uma tabela não otimizada, use o DW como exemplo, onde houver o mínimo de junções possível para acelerar a recuperação de dados). Além disso, se você usar UTF que também pode interferir no mecanismo de banco de dados (já vi alguns casos).
Pessoalmente, por minha própria experiência, um índice organizado adequadamente pode aumentar a velocidade de uma junção em ~ 70%, e fazer uma junção em uma coluna inteira pode acelerar a junção em cerca de ~ 25% (dependendo dos dados) . À medida que as tabelas principais começam a crescer e essas tabelas são usadas nelas, você prefere que um tipo de dados inteiro ocupe a coluna que possui alguns bytes versus um campo VARCHAR / CHAR que ocupará mais espaço. Tudo se resume a economizar espaço em disco, aumentar o desempenho e a estrutura geral de um banco de dados relacional.
Além disso, como James Snell mencionou:
Portanto, levando isso em consideração, você prefere atualizar 1 registro vinculado a um número, em vez de atualizar esse registro mais todos os registros da tabela na qual você se associa.
fonte
small project
ebigger
, atualize para esclarecer por que isso importa.Se você adotar a abordagem "Eu uso chaves substitutas o tempo todo", poderá ignorar esse tipo de preocupação. Isso pode não ser uma coisa boa, porque é importante pensar um pouco nos dados, mas certamente economiza muito tempo, energia e esforço. Se alguém adotasse uma aceitação dessa regra, os exemplos listados certamente se qualificam porque é necessário um "ato do congresso" próximo para fazer a alteração.
Consultas ad hoc de um banco de dados com essas chaves naturais são certamente úteis. A criação de visualizações que fazem a mesma coisa incluindo as tabelas de pesquisa também pode funcionar. Os bancos de dados modernos fazem um trabalho muito melhor com esse tipo de coisa, a tal ponto que provavelmente não importa.
Existem alguns casos específicos nos EUA, nos quais os padrões foram alterados drasticamente: o código postal foi expandido de 5 a 9 dígitos, as abreviações do Estado para 2 letras consistentes e se livram do período (lembre-se de quando Illinois estava doente?) E a maioria das o mundo conseguiu lidar com o ano 2000. Se você tem um aplicativo em tempo real com dados espalhados por todo o mundo contendo bilhões de registros, as atualizações em cascata não são a melhor ideia, mas todos nós devemos trabalhar em locais que enfrentam esses desafios? Com esse conjunto de dados, você pode testá-lo e obter uma resposta mais difinitiva.
fonte