Chaves primárias de caractere vs número inteiro

30

Estou projetando um banco de dados com várias tabelas de pesquisa contendo possíveis atributos das principais entidades. Estou pensando em usar uma chave de 4 ou 5 caracteres para identificar esses valores de pesquisa, em vez de um número inteiro com auto incremento, para que, quando armazenar esses IDs de atributo nas tabelas principais, verei valores significativos em vez de apenas números aleatórios.

Quais são as implicações de desempenho do uso de um campo de caractere como chave primária, e não como número inteiro?

Estou usando o MySQL, se isso importa.

[Editar]
Essas tabelas de pesquisa têm novos registros adicionados com pouca frequência. Eles são mantidos manualmente e as chaves baseadas em caracteres também são criadas manualmente. Aqui está um exemplo:

      CUISINES
 ID      Description
-----  --------------
CHNSE  Chinese
ITALN  Italian
MXICN  Mexican
BenV
fonte

Respostas:

22

Depende do seu motor. O senso comum é que as leituras são baratas, alguns bytes aqui e ali não afetarão significativamente o desempenho de um banco de dados de tamanho pequeno a médio.

Mais importante, depende dos usos para os quais você colocará a chave primária. Seriais inteiros têm a vantagem de serem simples de usar e implementar. Eles também, dependendo da implementação específica do método de serialização, têm a vantagem de serem deriváveis rapidamente , pois a maioria dos bancos de dados armazena o número de série em um local fixo, em vez de derivá-lo rapidamenteSelect max(ID)+1 from foo .

A questão é: como uma chave de 5 caracteres apresenta um "valor significativo" para você e para o aplicativo? Como esse valor é criado e leva mais ou menos tempo do que encontrar um número de série incremental. Embora exista uma quantidade trivial de espaço economizado em alguns números inteiros, a grande maioria dos sistemas ignorará essa economia de espaço.

Não há implicações no desempenho, exceto que o esquema de caracteres exige que nunca exista um mecanismo automático, pois suas "chaves" são inseparáveis. Para seu domínio específico, não se preocupe com chaves artificiais e use apenas chinês, japonês e tailandês como nomes de chave. Embora você não possa garantir exclusividade em relação a qualquer aplicativo possível, no seu escopo, é muito mais razoável usá-los em vez de abreviações horríveis e forçadas de 5 caracteres. Não há impactos significativos no desempenho até você chegar aos milhões de tuplas.

Como alternativa, se você está apenas rastreando por país de origem e não por cozinhas regionais específicas (cantonês, sichuan, siciliano, umbriano, calabrês, iucatecano, oaxacano etc.), sempre pode usar os códigos ISO 3166 .

Se eu tiver 10.000 receitas, a diferença entre uma chave de 5 e 20 caracteres não começa a somar?

O espaço é barato . Quando você estiver falando de 10.000.000 de receitas nas quais está executando operações OLAP, talvez. Com 10 mil receitas, você está vendo 150 mil de espaço.

Mas, novamente, depende. Se você possui muitos milhões de registros e faz junções neles, faz sentido desnormalizar a pesquisa de algo tão trivial (em uma visão materializada). Para todos os fins práticos, a eficiência de junção relativa em uma máquina moderna entre uma chave de 5 caracteres e uma chave de comprimento variável é tão semelhante a ser idêntica. Felizmente, vivemos em um mundo de CPU e disco abundantes. Os desagradáveis ​​são muitas junções e ineficiência de consulta, em vez de comparação caractere por caractere. Com isso dito, sempre teste .

As coisas de P&T desse nível são tão dependentes do banco de dados que as generalizações são extremamente difíceis. Crie dois modelos de amostra do banco de dados, preencha-os com o número estimado de registros e veja qual é mais rápido. Na minha experiência, o tamanho dos caracteres não faz uma grande diferença em comparação com bons índices, boas configurações de memória e outros elementos críticos de ajuste de desempenho.

Brian Ballsun-Stanton
fonte
@ BrianBallsun-Stanton Se você tiver dados sequenciais volumosos relacionados a essas tabelas de pesquisa, o espaço de armazenamento não será barato (em termos de velocidade da consulta) porque a velocidade de leitura do disco é o gargalo em qualquer RDB que não pode ser armazenado em cache inteiramente na RAM. Descobri isso ao tentar desenvolver um esquema de RDB que possa competir com os melhores do negócio de DB da série temporal. Divulgação completa, não tenho relação com o Skyspark, exceto pelo fato de eles cobrarem muito do meu empregador pelo uso de seu DB muito eficiente.
hobs
8

Eu acho que não há problema com o desempenho para tabela raramente alterada. Talvez você tenha problemas com o design no futuro. Sugiro que você não use dados corporativos como chave primária devido a alterações nos negócios. Use qualquer chave primária adicional para "vincular" tabelas no seu modelo. Quaisquer alterações nos negócios NÃO afetarão as tabelas relacionadas a esta.

garik
fonte
3

A verdadeira questão é se o desempenho da consulta ao banco de dados é significativo para o seu aplicativo (tamanho dos dados). Se sua consulta demorar microssegundos, salvar alguns desses microssegundos usando Intchaves não valerá a pena de legibilidade / manutenção. No entanto, se sua consulta demorar alguns minutos, salvar alguns desses minutos pode valer a pena.Int .

Abaixo está o motivo pelo qual acho que os números inteiros podem economizar seu tempo de consulta (como uma porcentagem do seu tempo total de consulta), mas os fundadores do SkySpark podem explicar melhor do que eu . Divulgação completa, meu empregador paga muito dinheiro ao SkySpark para usar o banco de dados e estou tentando criar algo melhor / mais rápido.

Se você tiver muitos dados sequenciais (arquivos de log, séries temporais, análises, corpora de texto ou fala) que possuem links (relacionamentos) para qualquer uma das suas tabelas de pesquisa, descobrirá que o espaço de armazenamento é crítico para a velocidade da consulta, apesar de @ A análise correta de Ballsun-Stanton de quão barato é o espaço em US $. Como a maior parte do tempo de consulta (para dados seqüenciais) é gasta na leitura do disco, o espaço não é barato em termos de tempo (como uma porcentagem do tempo total de consulta). Portanto, a menos que seu RDB compacte / descompacte automaticamente e eficientemente todas as chaves estrangeiras (chaves para registros relacionados), você desejará que todas as suas chaves estejam no que você pode fazer com linhas de dados compactadas (somente leitura). Em outras palavras, números inteiros automaticamente incrementados são compactados o máximo possível em teoriaInt , que são as mais eficientes em termos de espaço em disco (e velocidade de leitura) por unidade de informação conteúdo (entropia). FYI MyISAM no MySql impõe restrições, dada a baixa limitação de tamanho mínimo na maioria dos campos inteiros do banco de dados. E essa compressão vem sem:

  1. penalidade de compactação / descompactação no momento da consulta
  2. penalidade de leitura de disco no momento da consulta
  3. somente leitura ou outras restrições de banco de dados em chaves ou registros de dados compactados

Há uma razão pela qual ORMs populares e eficientes, como o Django, padronizam os números inteiros de incremento automático para PKs e outras questões SO chegaram à mesma conclusão.

fogão
fonte