Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Quelles sont les meilleures pratiques pour utiliser un GUID comme clé primaire, en particulier en ce qui concerne les performances ?

Les GUID peuvent sembler être un choix naturel pour votre clé primaire - et si vous le devez vraiment, vous pourriez probablement argumenter pour l'utiliser pour la CLÉ PRIMAIRE de la table. Ce que je déconseille fortement de faire utilise la colonne GUID comme clé de clustering , 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 :

  1. la clé primaire est une construction logique - l'une des clés candidates qui identifie 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 - choisissez ce qui convient le mieux à votre scénario.

  2. la clé de clustering (la colonne ou les colonnes qui définissent "l'index clusterisé" sur la table) - c'est un physique chose liée au stockage, et ici, un petit type de données stable et en constante augmentation est votre meilleur choix - INT ou BIGINT comme option par défaut.

Par défaut, la clé primaire d'une table SQL Server est également utilisée comme clé de clustering - mais cela n'a pas besoin d'être ainsi ! J'ai personnellement constaté des gains de performances considérables lors de la séparation de la précédente clé primaire/cluster basée sur le GUID en deux clés distinctes - la clé primaire (logique) sur le GUID et la clé de clustering (commande) sur un INT IDENTITY(1,1) colonne.

Comme Kimberly Tripp - la reine de l'indexation - et d'autres l'ont déclaré à maintes reprises - un GUID car la clé de clustering n'est pas optimale, car en raison de son caractère aléatoire, elle entraînera une fragmentation massive des pages et des index et des performances généralement médiocres.

Oui, je sais - il y a newsequentialid() dans SQL Server 2005 et plus - mais même cela n'est pas vraiment et entièrement séquentiel et souffre donc également des mêmes problèmes que le GUID - juste un peu moins en évidence.

Ensuite, il y a un autre problème à considérer :la clé de clustering d'une table sera également ajoutée à chaque entrée de chaque index non clusterisé de votre table - vous voulez donc vraiment vous assurer qu'elle est aussi petite que possible. Typiquement, un INT avec plus de 2 milliards de lignes devrait être suffisant pour la grande majorité des tables - et par rapport à un GUID en tant que clé de clustering, vous pouvez économiser des centaines de mégaoctets de stockage sur disque et dans la mémoire du serveur.

Calcul rapide - en utilisant INT vs GUID comme clé primaire et clé de cluster :

  • Table de base avec 1 000 000 lignes (3,8 Mo contre 15,26 Mo)
  • 6 index non clusterisés (22,89 Mo contre 91,55 Mo)

TOTAL :25 Mo contre 106 Mo - et c'est juste sur une seule table !

Un peu plus de matière à réflexion - d'excellents trucs de Kimberly Tripp - lisez-le, relisez-le, digérez-le ! C'est vraiment l'évangile de l'indexation SQL Server.

  • GUID en tant que PRIMARY KEY et/ou clustered key
  • Le débat sur l'index clusterisé se poursuit
  • Clé de clustering en constante augmentation :le débat sur l'index clusterisé... encore une fois !
  • L'espace disque est bon marché - ce n'est pas l'essentiel !

PS :bien sûr, si vous n'avez affaire qu'à quelques centaines ou quelques milliers de lignes, la plupart de ces arguments n'auront pas vraiment d'impact sur vous. Cependant :si vous entrez dans les dizaines ou les centaines de milliers de lignes, ou si vous commencez à compter en millions - alors ces points deviennent très cruciaux et très importants à comprendre.

Mise à jour : si vous voulez avoir votre PKGUID colonne comme clé primaire (mais pas votre clé de clustering), et une autre colonne MYINT (INT IDENTITY ) comme clé de clustering - utilisez ceci :

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

Fondamentalement :il vous suffit de explicitement dire la PRIMARY KEY contrainte qu'il est NONCLUSTERED (sinon, il est créé en tant qu'index clusterisé, par défaut) - puis vous créez un deuxième index défini comme CLUSTERED

Cela fonctionnera - et c'est une option valable si vous avez un système existant qui doit être "repensé" pour des performances. Pour un nouveau système, si vous partez de zéro et que vous n'êtes pas dans un scénario de réplication, je choisirais toujours ID INT IDENTITY(1,1) comme ma clé primaire en cluster - bien plus efficace qu'autre chose !