Por que o uso de chaves de cadeia geralmente é considerado uma má ideia?

24

Isso tem me incomodado por algum tempo. Na maioria das vezes, quando se trata de armazenar dados em estruturas como hashtables, programadores, livros e artigos, insiste em que os elementos de indexação nessas estruturas por valores de String são considerados uma má prática. No entanto, até agora, não encontrei uma única fonte para explicar também por que é considerada uma prática ruim. Depende da linguagem de programação? Na estrutura subjacente? Na implementação?

Veja dois exemplos simples, se ajudar:

Uma tabela semelhante a SQL em que as linhas são indexadas por uma chave primária String.

Um dicionário .NET em que as chaves são cadeias de caracteres.


fonte
9
Ter chaves de seqüência de caracteres não é uma má idéia em geral. Eu suspeito que essas declarações foram feitas em um contexto em que um tipo de chave melhor está disponível. Eu tenho dicionários .net com chaves de string o tempo todo. Você pode dar alguns exemplos dessa afirmação?
código é o seguinte
3
Você geralmente deseja chaves primárias que não mudam ao longo da vida útil de um objeto / linha. Por exemplo, usernamecomo a chave primária de uma userstabela provavelmente não é a melhor ideia, você prefere um ID de incremento automático. Mas isso usernameé uma string é apenas acessório, sendo uma propriedade mutável é o problema principal
CodesInChaos
Em um banco de dados, considere como indexaria seqüências de caracteres em oposição a números inteiros.
@CodesInChaos Gostaria de me lembrar de onde encontrei a maioria dos casos, mas por enquanto posso colar a parte que me lembrou o problema. Era de uma apresentação de slides da GDC da Valve que discutia diálogos de jogos e armazenava fatos sobre o mundo em pares <key = string, value = object>.
2
Strings estão bem. Apenas não cordas 'mágicas'. Portanto, ao usar uma tabela de hash, verifique se você não possui strings nuas no seu código. Você deve evitar grandes valores de texto como chaves, porque eles não apresentam um bom desempenho, mas na maioria das situações do mundo real, uma cadeia de texto curta é tão rápida quanto um número inteiro (eles não são bancos de dados maciços). Você também pode usar teclas alternativas, por exemplo, a chave primária é um número, mas também há uma 'lesma' ou sequência única que também é única.
Ipaul 03/03

Respostas:

17

Tudo tem a ver com as duas coisas basicamente:

1) A velocidade da pesquisa (onde números inteiros, por exemplo, se saem muito melhor)

2) O tamanho dos índices (onde os índices de string explodiriam)

Agora tudo depende das suas necessidades e do tamanho do conjunto de dados. Se uma tabela ou uma coleção tiver entre 10 e 20 elementos, o tipo de chave é irrelevante. Será muito rápido, mesmo com uma chave de cadeia.

O PS pode não estar relacionado à sua pergunta, mas os Guids também são considerados inválidos para as chaves do banco de dados (Guid de 16 bytes vs. número inteiro de 4 bytes). Em grandes volumes de dados, os Guids diminuem a velocidade da pesquisa.

Coelho
fonte
Nem sempre - GUIDs incrementais são possíveis. Os índices ainda serão maiores, mas a penalidade de pesquisa não será tão ruim.
Sam
7
Na verdade, eles estão bem. Você deve observar a relação entre o tempo de E / S do disco de tempo e a comparação de valores na memória. Como os tempos de acesso ao disco sobrecarregam a comparação de memória, a única coisa que realmente importa na análise do desempenho do banco de dados é a E / S. Se a chave é um GUID, sequência ou número inteiro, isso não é realmente crítico. O tamanho do índice afeta quantos valores de índice cabem em uma página, mas se a chave é um int de 4 bytes (que pode não ser grande o suficiente e não pode ser gerado pelo cliente) ou um valor de 16 bytes não é uma preocupação significativa. Em alguns bancos de dados, os rowId's podem ter 16 bytes de tamanho.
Ipaul 03/03
9

Há mais um problema com o uso de cadeias de caracteres como chaves ou, mais precisamente, usando literais de cadeias de caracteres como chaves, deixando de lado motivos puros de desempenho / eficiência. Erros de digitação. Se você usa literais de string como chaves em um dicionário, está se preparando para uma surpresa desagradável quando alguém "ReceiverId"se torna um "RecieverId". Configure constantes para armazenar os valores-chave e reutilizá-los sempre que você acessar o dicionário.

Trivial e óbvio, você pode dizer, mas um número impressionante de exemplos de código .NET em toda a Web usa literais de string, propagando essa prática duvidosa. O ASP.NET com todas as sessões, ViewStates e QueryParams espalhados pela base de código é particularmente culpado aqui.

scrwtp
fonte
IMHO não é trivial. Eu também vi casos em que existem chaves "1"e "1 "na mesma tabela.
precisa saber é
Torne-se ainda mais divertido quando você joga a sensibilidade do case na mistura também. Vimos muitas pessoas, inclusive eu, tropeçando diretamente nessa.
Tony Hopkinson
Ainda melhor do que usar constantes, pelo menos em C #, é usar Expressões. Dessa forma, você pode gerar suas strings a partir dos nomes de métodos / propriedades, etc., para que suas pesquisas se tornem seguras e fáceis de refatorar.
GoatInTheMachine
4

Existem muitas vantagens e desvantagens aqui. Na verdade, eu uso chaves de string com frequência, mas geralmente incluo chaves secundárias substitutas para junções (obviamente seria o contrário se eu estivesse usando o MySQL). Existem casos em que não o faço.

Primeiro, sou fã de declarar chaves naturais como a chave primária em que o banco de dados pode lidar com isso muito bem (PostgreSQL, por exemplo). Isso ajuda na normalização e facilita o design do banco de dados. Chaves substitutas facilitam a união.

Há duas razões pelas quais geralmente adiciono chaves substitutas:

  1. Nem sempre é claro o que é uma chave natural. Às vezes, esses precisam ser alterados. Alterar uma chave composta natural quando é usada para junções e integridade referencial é complicada e propensa a erros.

  2. O desempenho da junção em chaves compostas é problemático e, quando você segue a rota da chave natural, fica preso lá.

Nos casos em que uma chave natural é de definição, coluna única e texto, no entanto, eu geralmente ingresso na chave de cadeia. Minha razão para fazer isso é que isso geralmente evita a junção na pesquisa. O uso mais comum é fornecer design de banco de dados adequado ao caso de uso dos tipos de enumeração. Na maioria dos casos, eles não exigem a junção extra para consultas de rotina. Portanto, onde for esse o caso, chaves de cadeia como chaves de junção fazem todo sentido.

Por exemplo, no LedgerSMB, armazenamos categorizações de conta. Eles são identificados por referência de sequência. E alguns outros dados são armazenados com a referência de sequência usada para impor regras relacionadas às combinações de categorizações que podem afetar uma conta. O único momento em que a lógica é necessária é ao salvar um conjunto de categorizações, então juntamos a chave da string.

Quanto ao motivo pelo qual o padrão seria chaves inteiras, não acho que seja apenas uma questão de tamanho do índice. Um grande problema é o gerenciamento de chaves. Como a chave é arbitrária e você pode estar lidando com milhões de registros, é necessário ter uma maneira de gerar strings exclusivas. Há casos em que as pessoas usam UUIDs para isso, mas há uma chance diferente de zero de colisão de UUID e, onde bilhões de registros são armazenados, essa chance se torna alta o suficiente para que se possa ver enquanto a chance de colisão com tipos inteiros incrementados é zero por definição.

Chris Travers
fonte
Não é diferente de zero se você conseguir fazer com que o tipo inteiro retorne a zero. Para um tipo não assinado de 32 bits, que só é 4G distância, que é perturbadoramente próximo com “milhares de milhões de registros” ...
Donal Fellows
Se você tem um banco de dados que pode dizer "erro em vez de contornar", é zero. De qualquer forma, é mais fácil gerenciar a possibilidade de colisão com números inteiros incrementados do que com valores pseudo-aleatórios.
Chris Travers
1

Existem vários problemas em potencial com o uso de strings como chaves, especialmente quando se trata de tabelas do tipo sql. Como mencionado por @bunny, os índices para suas tabelas serão maiores, mas acho que de maneira mais significativa, qualquer relacionamento de chave estrangeira com a tabela envolverá AMBAS as tabelas para conter a string em oposição a um identificador de peso leve (número inteiro) . Se você achar que existem ainda mais tabelas com referências à primeira, as chaves de sequência serão proliferadas em todo o banco de dados.

Matthew Flynn
fonte
1

Não é uma má idéia por si só, é geralmente com uma visão tardia de 20/20 um comprometimento ruim do design. A flexibilidade e o alcance da cadeia de caracteres versus o custo e a complexidade adicionais.

Se o número inteiro executar o trabalho de maneira inteligente e a maior parte do processamento caro não precisar saber o que o número inteiro representa, use um.

Tony Hopkinson
fonte
0

De alguma forma, você recuperou os dados incorretos de um Hashtable.

Você quis dizer "DaytimeTelephone" ou "EveningTelephone"?

ou

Você quis dizer 1234567 ou 1234576?

Embora os números sejam indiscutivelmente mais eficientes para a máquina , sempre que as coisas dão errado (e acontecem), cabe a você e eu entender o que aconteceu e, nesse ponto, economizar alguns bytes de armazenamento e alguns micro (nano?) segundos de processamento perdem a nitidez toda vez.

Phill W.
fonte
1
E, assim, você acaba com uma lista de constantes, usando o nome da constante em seu código para representar o número mágico ... Java enumera o resgate para abstraí-lo ainda mais e deixando você apenas com o nome e com o ordinal mapeamento invisível.
Jwenting
-1

Muitas vantagens e desvantagens. Muitos programadores nunca considerariam usar chaves de seqüência de caracteres no banco de dados porque não estão cientes do hash e de como um banco de dados funciona. As chaves de cadeia, desde que sejam extremamente estáveis ​​ou sem sentido (substitutos), são uma boa opção de design em muitas circunstâncias.

moss23
fonte
2
Esta resposta não adiciona nada que ainda não tenha sido dito nas outras respostas, que dizem melhor.
precisa saber é o seguinte
-2

chave de cadeia fará sentido, quando se trata de tabela de pesquisa com cerca de 10 a 100 registros de cadeia curta; os dados relacionados são mais legíveis + por exemplo, rastreamento de alterações (ID numérico / de guia vs. sequência, por exemplo, "Administrador"); Por outro lado, o banco de dados de associação do ASP.NET usa chaves de seqüência de caracteres para AspNetRoles.

Alfred Hitchcock
fonte