Une chose à considérer est qu'une clé primaire et un index cluster ne sont pas la même chose. Une clé primaire est une contrainte et traite des règles de vie des données (c'est-à-dire l'intégrité des données); cela n'a rien à voir avec l'efficacité / la performance. Une clé primaire nécessite que la ou les colonnes de clé soient uniques (en combinaison) et NON NULES (individuellement). Un PK est appliqué via un index unique, bien qu'il puisse être en cluster ou non en cluster.
Un index clusterisé est un moyen de classer physiquement (c'est-à-dire sur disque) les données de la table et traite des performances; cela n'a rien à voir avec l'intégrité des données. Un index clusterisé peutexiger que la ou les colonnes clés soient uniques (en combinaison), mais ce n'est pas nécessaire. Cependant, étant donné que l'index cluster est l'ordre physique des données, il doit identifier de manière unique chaque ligne, quoi qu'il arrive. Donc, si vous ne le définissez pas pour exiger l'unicité, il créera sa propre unicité via une colonne "uniquifier" de 4 octets cachée. Cette colonne est toujours présente dans les index cluster non uniques, mais elle ne prend pas de place lorsque les champs clés sont uniques (en combinaison). Pour voir de première main comment fonctionne cette colonne "uniquifier" (à la fois dans l'index clusterisé et l'effet sur les index non clusterisés), veuillez consulter ce script de test que j'ai publié sur PasteBin: script T-SQL pour tester la taille de l'uniquificateur .
D'où la question principale de:
serait-il plus efficace d'ajouter un id
champ d' incrémentation automatique et de l'utiliser en conjonction avec company_id
comme clé primaire, ou ajouterait-il une surcharge inutile
confond ces deux concepts, ils doivent donc être traités séparément, bien qu'il y ait certainement un certain chevauchement.
Faut- IDENTITY
il ajouter une colonne ou serait-ce une surcharge inutile?
Si vous ajoutez une INT IDENTITY
colonne et l'utilisez pour créer un PK, en supposant qu'il s'agisse d'un PK en cluster, cela ajoute 4 octets à chaque ligne. Cette colonne est visible et utilisable dans les requêtes. Il pourrait être ajouté à d'autres tables en tant que clé étrangère, mais dans ce cas particulier, cela ne se produira pas.
Si vous n'ajoutez pas la INT IDENTITY
colonne, vous ne pouvez pas créer de PK sur cette table. Cependant, vous pouvez toujours créer un index cluster sur la table tant que vous n'utilisez pas l' UNIQUE
option. Dans ce cas, SQL Server ajoutera une colonne masquée appelée "uniquifier" qui se comporte comme décrit ci-dessus. Étant donné que la colonne est masquée, elle ne peut pas être utilisée dans les requêtes ou comme référence pour les clés étrangères.
En ce qui concerne l'efficacité, ces options sont à peu près les mêmes. Oui, il y aura un peu moins d'espace occupé en ayant l'index cluster non unique en raison du fait que certaines lignes (celles avec les valeurs de clé uniques initiales) IDENTITY
occupent 0 octet tandis que toutes les lignes dans / PK prendront les 4 octets. Mais il n'y aura pas assez de lignes de 0 octet (en particulier avec la petite quantité de lignes attendue) pour remarquer une différence, sans parler de la commodité de pouvoir utiliser la ID
colonne dans les requêtes.
INT IDENTITY Column ou Hash of org_path
Persisted Computed Column?
Étant donné que vous ne rechercherez pas de lignes en fonction de org_path
valeurs, il n'est pas logique d'ajouter la surcharge de la colonne calculée persistante et de devoir calculer ce hachage dans les requêtes afin de les comparer à la colonne calculée (c'était ma suggestion originale, disponible dans l'historique des révisions ici , qui était basée sur le libellé initial / les détails de la question). Dans ce cas particulier, la INT IDENTITY
colonne "ID" est probablement la meilleure.
Ordre des colonnes clés
Étant donné que la ID
colonne sera rarement, voire jamais, utilisée dans les requêtes, et étant donné que les deux principaux cas d'utilisation sont d'obtenir "toutes les lignes" ou "toutes les lignes pour une donnée company_id
", je créerais le PK company_id, id
. Et parce que cela signifie que les lignes ne sont pas insérées séquentiellement, je spécifierais un FILLFACTOR
de 90. Vous devrez également vous assurer de faire une maintenance d'index régulière pour réduire la fragmentation.
Deuxième question
le fait que company_id est la clé primaire dans une autre table a-t-il un effet ici
Non.
Déclencheur
Étant donné que les org_path
valeurs dans un company_id
sont uniques, vous devez toujours créer un déclencheur INSERT, UPDATE
pour appliquer ce paramètre. Dans le déclencheur, faites un IF EXISTS
avec une requête qui fait probablement un COUNT(*)
et GROUP BY company_id, org_path
. Si quelque chose est trouvé, émettez un ROLLBACK
pour annuler l'opération DML, puis RAISERROR
dites qu'il y a des doublons.
Collation
Dans ma réponse initiale (basée sur le libellé original / des détails clairsemés de la question, et disponibles dans l'historique des révisions ici ), j'avais suggéré d'utiliser éventuellement un classement binaire (c'est-à-dire _BIN2
). Maintenant que nous avons une idée de ce qu'est exactement org_path
, je ne recommanderais pas d' utiliser un classement binaire. Comme il y aura des signes diacritiques, vous ne voulez utiliser des équivalences linguistiques.