Les GUID peuvent sembler être un choix naturel pour votre clé primaire - et si vraiment nécessaire, vous pourriez probablement argumenter pour l'utiliser comme CLÉ PRIMAIRE de la table. Ce que je recommande fortement de ne pas faire est d'utiliser la colonne GUID comme clé de regroupement, ce que SQL Server fait par défaut, à moins que vous ne lui disiez spécifiquement de ne pas le faire.
Vous devez vraiment séparer deux problèmes:
-
la clé primaire est un concept logique - l'une des clés candidates qui identifient de manière unique et fiable chaque ligne de votre table. Cela peut être n'importe quoi, vraiment - un INT
, un GUID
, une chaîne de caractères - choisissez ce qui a le plus de sens pour votre scénario.
-
la clé de regroupement (la colonne ou les colonnes qui définissent l'«index regroupé» sur la table) - c'est une chose liée au stockage physique, et ici, un type de données petit, stable et toujours croissant est le meilleur choix - INT
ou BIGINT
comme option par défaut.
Par défaut, la clé primaire sur une table SQL Server est également utilisée comme clé de regroupement - mais cela n'a pas besoin d'être ainsi! J'ai personnellement constaté des gains de performance massifs en séparant la clé primaire/principale basée sur GUID en deux clés distinctes - la clé primaire (logique) sur le GUID, et la clé de regroupement (d'ordonnancement) sur une colonne INT IDENTITY(1,1)
distincte.
Comme Kimberly Tripp - la Reine de l'Indexation - et d'autres l'ont dit de nombreuses fois - un GUID
en tant que clé de regroupement n'est pas optimal, car en raison de sa randomité, cela entraînera une fragmentation massive des pages et des index et une performance généralement médiocre.
Oui, je sais - il y a newsequentialid()
dans SQL Server 2005 et plus - mais même cela n'est pas vraiment et totalement séquentiel et souffre donc des mêmes problèmes que le GUID
- juste un peu moins proéminemment.
Il y a ensuite un autre point à considérer: la clé de regroupement sur une table sera ajoutée à chaque entrée de chaque index non regroupé sur votre table également - donc vous voulez vraiment vous assurer qu'elle est aussi petite que possible. En général, un INT
avec 2+ milliards de lignes devrait suffire pour la grande majorité des tables - et par rapport à un GUID
en tant que clé de regroupement, vous pouvez vous économiser des centaines de mégaoctets de stockage sur disque et en mémoire serveur.
Calcul rapide - en utilisant INT
vs. GUID
en tant que Clé Primaire et de Regroupement:
- Table de base avec 1 000 000 lignes (3,8 Mo vs. 15,26 Mo)
- 6 index non regroupés (22,89 Mo vs. 91,55 Mo)
TOTAL: 25 Mo vs. 106 Mo - et c'est juste pour une seule table!
Un peu plus à réfléchir - excellentes informations de la part de Kimberly Tripp - lisez-le, relisez-le, assimilez-le! C'est un véritable évangile de l'indexation SQL Server.
PS: bien sûr, si vous traitez seulement quelques centaines ou quelques milliers de lignes - la plupart de ces arguments n'auront pas vraiment beaucoup d'impact sur vous. Cependant: si vous atteignez les dizaines ou les centaines de milliers de lignes, ou que vous commencez à compter en millions - alors ces points deviennent très cruciaux et très importants à comprendre.
Mise à jour: si vous voulez avoir votre colonne PKGUID
comme votre clé primaire (mais pas votre clé de regroupement), et une autre colonne MYINT
(INT IDENTITY
) comme votre clé de regroupement - utilisez ceci:
CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
MyINT INT IDENTITY(1,1) NOT NULL,
.... ajoutez plus de colonnes au besoin ...... )
ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)
CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)
Fondamentalement: vous devez simplement dire explicitement à la contrainte de PRIMARY KEY
qu'elle est NONCLUSTERED
(sinon elle est créée comme votre index regroupé, par défaut) - puis vous créez un deuxième index défini comme CLUSTERED
Cela fonctionnera - et c'est une option valide si vous avez un système existant qui doit être "reconçu" pour la performance. Pour un nouveau système, si vous partez de zéro, et que vous n'êtes pas dans un scénario de réplication, alors je choisirais toujours ID INT IDENTITY(1,1)
comme ma clé primaire de regroupement - beaucoup plus efficace que tout autre chose!
24 votes
Le problème n'est pas censé se produire. Si votre PK est regroupée, alors presque chaque insertion a le potentiel de causer une division de la page. Dans les versions modernes de SQL Server, cela a été "corrigé" avec NEWSEQUENTIALID(), mais cela perd l'avantage de pouvoir le calculer à l'avance. Je vous recommande fortement de vous renseigner sur les GUID ailleurs car cette question est beaucoup trop générale et risque probablement de déclencher une bataille religieuse qui pourrait durer des heures...
5 votes
Je voudrais également ajouter que le mot serveur est ambigu dans Je veux attribuer le GUID côté serveur (ne veux pas laisser SQL créer le GUID).
0 votes
Cette question présente des similitudes avec ce "sql-server-guid-sort-algorithm-why" stackoverflow.com/questions/7810602/…
0 votes
@AaronBertrand Tu saurais. Le problème est supposé, non pas parce qu'il n'est pas mesurable, mais parce qu'il est négligeable.