web-dev-qa-db-fra.com

Pourquoi l'utilisation des clés de chaîne est-elle généralement considérée comme une mauvaise idée?

Cela me dérange depuis un moment. La plupart du temps, lorsqu'il s'agit de stocker des données dans des structures telles que des tables de hachage, des programmeurs, des livres et des articles insistent sur le fait que l'indexation des éléments dans ces structures par des valeurs de chaîne est considérée comme une mauvaise pratique. Pourtant, jusqu'à présent, je n'ai pas trouvé une seule source de ce type pour expliquer également POURQUOI elle est considérée comme une mauvaise pratique. Cela dépend-il du langage de programmation? Sur le cadre sous-jacent? Sur la mise en œuvre?

Prenez deux exemples simples, si cela vous aide:

Une table de type SQL où les lignes sont indexées par une clé primaire String.

Un dictionnaire .NET où les clés sont des chaînes.

25
user52800

Tout cela a à voir avec les deux choses essentiellement:

1) La vitesse de recherche (où les entiers, par exemple, se portent beaucoup mieux)

2) La taille des index (où les index de chaîne exploseraient)

Maintenant, tout dépend de vos besoins et de la taille de l'ensemble de données. Si une table ou une collection contient 10 à 20 éléments, le type de clé n'est pas pertinent. Ce sera très rapide même avec une clé de chaîne.

P.S. Peut ne pas être lié à votre question, mais les guides sont également considérés comme mauvais pour les clés de base de données (Guid de 16 octets contre un entier de 4 octets). Sur les gros volumes de données, les GUID ralentissent la recherche.

18
bunny

Il y a un autre problème avec l'utilisation de chaînes comme clés, ou plus précisément, l'utilisation de littéraux de chaîne comme clés, en mettant de côté des raisons de performances/efficacité pures. Typos. Si vous utilisez des littéraux de chaîne comme clés dans un dictionnaire, vous vous préparez une mauvaise surprise quand un "ReceiverId" devient un "RecieverId". Configurez des constantes pour stocker les valeurs clés et réutilisez-les chaque fois que vous accédez au dictionnaire.

Privial et évident, vous pouvez dire, mais un nombre étonnant d'exemples de code .NET sur le Web utilise des littéraux de chaîne, propageant cette pratique douteuse. ASP.NET avec toutes les sessions, ViewStates et QueryParams disséminés dans la base de code est particulièrement coupable ici.

10
scrwtp

Il y a de nombreux compromis ici. En fait, j'utilise fréquemment des clés de chaîne, mais j'inclus souvent des clés secondaires de substitution pour les jointures (ce serait évidemment l'inverse si j'utilisais MySQL). Il y a des cas où je n'en ai pas cependant.

Tout d'abord, je suis fan de déclarer les clés naturelles comme clé primaire où la base de données peut bien gérer cela (PostgreSQL par exemple). Cela aide à la normalisation et permet une conception plus claire de la base de données. Les touches de substitution facilitent la connexion.

Il y a deux raisons pour lesquelles j'ajoute généralement des clés de substitution:

  1. On ne sait pas toujours ce qu'est une clé naturelle. Parfois, ceux-ci doivent être modifiés. Changer une clé composite naturelle lorsqu'elle est utilisée pour les jointures et l'intégrité référentielle est compliqué et sujet aux erreurs.

  2. Les performances de jointure sur les clés composites sont problématiques et une fois que vous suivez la route des clés naturelles, vous y êtes coincé.

Dans les cas où une clé naturelle est une définition, une seule colonne et du texte, cependant, je joins généralement la clé de chaîne. Ma raison est que cela évite souvent les jointures lors de la recherche. L'utilisation la plus courante consiste à fournir une conception de base de données appropriée autour du cas d'utilisation des types d'énumération. Dans la plupart des cas, ceux-ci nécessitent pas la jointure supplémentaire pour les requêtes de routine. Ainsi, lorsque c'est le cas, les clés de chaîne en tant que clés de jointure sont parfaitement logiques.

Par exemple, dans LedgerSMB, nous stockons les catégorisations de compte. Celles-ci sont identifiées par la référence de chaîne et certaines autres données sont stockées avec la référence de chaîne qui est utilisée pour appliquer les règles concernant les combinaisons de catégorisations qui peuvent affecter un compte. La seule fois où la logique est nécessaire est lors de l'enregistrement d'un ensemble de catégorisations, nous nous joignons donc à la clé de chaîne.

Quant à savoir pourquoi la valeur par défaut serait des clés entières, je ne pense pas que ce soit juste une question de taille d'index. Un gros problème est la gestion des clés. Étant donné que la clé est arbitraire et que vous pouvez avoir affaire à des millions d'enregistrements, vous devez avoir un moyen de générer des chaînes uniques. Il y a des cas où les gens utilisent des UUID pour cela, mais il y a une chance non nulle de collision UUID, et où des milliards d'enregistrements sont stockés, cette chance devient suffisamment élevée que l'on pourrait réellement voir tandis que la probabilité de collision avec des types entiers incrémentés est nulle par définition.

4
Chris Travers

Il existe un certain nombre de problèmes potentiels liés à l'utilisation de chaînes comme clés, en particulier lorsqu'il s'agit de tables de type SQL. Comme mentionné par @bunny, les index de vos tables vont être plus grands, mais je pense que plus important encore, toute relation de clé étrangère avec la table impliquera que LES DEUX tables contiennent la chaîne par opposition à un identificateur plus léger (entier) . Si vous trouvez qu'il y a encore plus de tables avec des références à la première, les clés de chaîne se multiplieront dans votre base de données.

1
Matthew Flynn

Ce n'est pas une mauvaise idée en soi, c'est généralement avec un recul de 20/20 un mauvais compromis de conception. La flexibilité et la gamme de cordes par rapport au coût et à la complexité supplémentaires.

Si l'entier fait la plage de travaux et que la majeure partie du traitement coûteux n'a pas besoin de savoir ce que l'entier représente, utilisez-en un.

1
Tony Hopkinson

Vous avez en quelque sorte récupéré les mauvaises données d'une table de hachage.

Voulez-vous dire "DaytimeTelephone" ou "EveningTelephone"?

ou

Voulez-vous dire 1234567 ou 1234576?

Alors que les nombres sont sans doute plus efficaces pour la machine, chaque fois que les choses tournent mal (et ils le font), il revient à des personnes comme vous et moi de donner un sens à ce qui s'est passé et , à ce stade, cette économie de quelques octets de stockage et de quelques micro (nano?) - secondes de traitement perd à clarté à chaque fois.

0
Phill W.