Clés primaires caractère vs entier

30

Je conçois une base de données avec plusieurs tables de recherche contenant les attributs possibles des entités principales. Je pense utiliser une clé à 4 ou 5 caractères pour identifier ces valeurs de recherche plutôt qu'un entier à incrémentation automatique afin que lorsque je stocke ces ID d'attribut sur les tables principales, je vois des valeurs significatives plutôt que des nombres aléatoires.

Quelles sont les implications en termes de performances de l'utilisation d'un champ de caractère comme clé primaire plutôt que comme un entier?

J'utilise MySQL si cela importe.

[Modifier]
Ces tables de recherche ont de nouveaux enregistrements ajoutés rarement. Ils sont gérés manuellement et les clés basées sur les caractères sont également créées manuellement. Voici un exemple:

      CUISINES
 ID      Description
-----  --------------
CHNSE  Chinese
ITALN  Italian
MXICN  Mexican
BenV
la source

Réponses:

22

Cela dépend de votre moteur. Il est communément admis que les lectures sont bon marché, quelques octets ici et là n'auront pas d'impact significatif sur les performances d'une base de données de petite à moyenne taille.

Plus important encore, cela dépend des utilisations auxquelles vous utiliserez la clé primaire. Les séries entières ont l'avantage d'être simples à utiliser et à mettre en œuvre. Ils ont également, selon la mise en œuvre spécifique de la méthode de sérialisation, l'avantage d'être rapidement dérivables, car la plupart des bases de données stockent simplement le numéro de série dans un emplacement fixe, plutôt que de le dériver Select max(ID)+1 from fooà la volée.

La question devient: comment une clé à 5 caractères présente-t-elle une "valeur significative" pour vous et pour l'application? Comment cette valeur est-elle créée et prend-elle plus ou moins de temps que la recherche d'un numéro de série incrémentiel? Bien qu'il y ait une quantité insignifiante d'espace économisé dans certains entiers, la grande majorité des systèmes ignoreront ces économies d'espace.

Il n'y a aucune incidence sur les performances, sauf que le schéma de caractères exige qu'il n'y ait jamais de moteur automatique, car vos "clés" sont indivisibles. Pour votre domaine spécifique, ne vous embêtez pas avec des clés artificielles et utilisez simplement le chinois, le japonais et le thaï comme noms de clé. Bien que vous ne puissiez pas garantir l'unicité de toute application possible, dans votre portée, il est beaucoup plus raisonnable de les utiliser au lieu d'abréviations horribles et forcées à 5 caractères. Il n'y a aucun impact significatif sur les performances tant que vous n'avez pas atteint les millions de tuples.

Alternativement, si vous effectuez un suivi par pays d'origine et non par des cuisines régionales spécifiques (cantonais, sichuan, sicilien, ombrien, calabrais, yucatèque, oaxaca, etc.), vous pouvez toujours utiliser les codes ISO 3166 .

Si j'ai 10 000 recettes, la différence entre une clé à 5 caractères et à 20 caractères ne commence-t-elle pas à s'additionner?

L'espace est bon marché . Lorsque vous parlez de 10 000 000 de recettes sur lesquelles vous effectuez des opérations OLAP, alors, peut-être. Avec 10 000 recettes, vous recherchez 150 000 d'espace.

Mais encore une fois, cela dépend. Si vous avez plusieurs millions d'enregistrements et que vous y effectuez des jointures, il est logique de dénormaliser la recherche de quelque chose d'aussi trivial (dans une vue matérialisée). À toutes fins pratiques, l'efficacité relative de la jonction sur une machine moderne entre une clé à 5 caractères et une clé à longueur variable est si similaire qu'elle est identique. Heureusement, nous vivons dans un monde de CPU et de disque abondants. Les méchants sont trop de jointures et d'inefficacité de requête, plutôt que de comparaison caractère par caractère. Cela dit, testez toujours .

Les choses P&T de ce niveau dépendent tellement de la base de données que les généralisations sont extrêmement difficiles. Créez deux exemples de modèles de la base de données, remplissez-les avec le nombre estimé d'enregistrements, puis voyez lequel est le plus rapide. D'après mon expérience, la longueur des caractères ne fait pas une énorme différence par rapport à de bons index, de bonnes configurations de mémoire et d'autres éléments de réglage des performances critiques.

Brian Ballsun-Stanton
la source
@ BrianBallsun-Stanton si vous avez des données séquentielles volumineuses qui se rapportent à ces tables de recherche, l'espace de stockage n'est pas bon marché (en termes de vitesse de requête) car la vitesse de lecture du disque est le goulot d'étranglement dans tout RDB qui ne peut pas être entièrement mis en cache dans la RAM. J'ai trouvé cela en essayant de développer un schéma RDB qui peut rivaliser avec les meilleurs de la série chronologique DB. Divulgation complète, je n'ai aucun lien avec Skyspark, sauf qu'ils facturent beaucoup à mon employeur pour l'utilisation de leur base de données très efficace.
plaques de cuisson
8

Je pense qu'il n'y a pas de problème de performances pour une table rarement modifiée. Peut-être que vous aurez des problèmes de conception à l'avenir. Je vous suggère de ne pas utiliser les données d'entreprise comme clé primaire en raison de changements commerciaux. Utilisez n'importe quelle clé primaire supplémentaire pour «lier» les tables de votre modèle. Aucun changement commercial n'aura d'impact sur les tables liées à celui-ci.

garik
la source
3

La vraie question est de savoir si les performances des requêtes DB sont importantes pour votre application (taille des données). Si votre requête prend des microsecondes, enregistrer quelques-unes de ces microsecondes à l'aide de Intclés ne vaut pas la peine de lisibilité / maintenabilité. Cependant, si votre requête prend quelques minutes, l'enregistrement de certaines de ces minutes peut valoir la peine de Intclés.

Voici pourquoi je pense que les entiers peuvent vous faire gagner du temps (en pourcentage du temps de requête global), mais les fondateurs de SkySpark peuvent l' expliquer mieux que moi . Divulgation complète, mon employeur paie à SkySpark beaucoup d'argent pour utiliser sa base de données et j'essaie de construire quelque chose de meilleur / plus rapide.

Si vous avez beaucoup de données séquentielles (fichiers journaux, séries chronologiques, analyses, corpus textuels ou vocaux) qui ont des liens (relations) vers l'une de vos tables de recherche, vous constaterez que l'espace de stockage est essentiel pour la vitesse des requêtes, malgré @ L'analyse correcte de Ballsun-Stanton sur la façon dont l' espace bon marché est en $. Étant donné que la plupart du temps de requête (pour les données séquentielles) est consacré à la lecture du disque, l'espace n'est pas bon marché en termes de temps (en pourcentage du temps de requête global). Donc, à moins que votre RDB comprime / décompresse automatiquement et efficacement toutes les clés étrangères (clés des enregistrements associés), vous voudrez que toutes vos clés soient Int, qui sont les plus efficaces en termes d'espace disque (et de vitesse de lecture) par unité d'information contenu (entropie). FYI MyISAM dans MySql impose des restrictionssur ce que vous pouvez faire avec les lignes de données compressées (lecture seule). En d'autres termes, les entiers incrémentés automatiquement sont déjà compressés autant que cela est théoriquement possible , étant donné la faible limitation de taille minimale sur la plupart des champs d'entiers DB. Et cette compression vient sans:

  1. pénalité de compression / décompression au moment de la requête
  2. pénalité de lecture sur disque au moment de la requête
  3. lecture seule ou autres restrictions de base de données sur les enregistrements de données compressés ou les clés

Il y a une raison pour laquelle les ORM populaires et efficaces comme Django par défaut incrémentent automatiquement les entiers pour les PK et pourquoi d'autres questions SO sont arrivées à la même conclusion.

des plaques
la source