Uniqueidentifier PK: un tas SQL Server est-il le bon choix?

D'ACCORD. J'ai lu des choses ici et là sur les tas de SQL Server, mais rien de trop définitif pour vraiment me guider. Je vais essayer de mesurer la performance, mais j'espérais des conseils sur ce que je devrais examiner. C'est SQL Server 2008 Enterprise. Voici les arrays:

Emplois

  • JobID (PK, GUID, généré de l'extérieur)
  • StartDate (datetime2)
  • Identifiant de count
  • Plusieurs autres domaines comptables, principalement des décimales et des bigints

JobSteps

  • JobStepID (PK, GUID, généré de l'extérieur)
  • JobID FK
  • Date de début
  • Plusieurs autres domaines comptables, principalement des décimales et des bigints

Utilisation: Beaucoup d'insertions (centaines / sec), généralement 1 JobStep par Job. Estimer peut-être 100-200M lignes par mois. Aucune mise à jour du tout, et les seules suppressions proviennent de l'archivage des données de plus de 3 mois.

Faire ~ 10 requêtes / sec contre datatables. Certains rejoignent JobSteps aux Jobs, d'autres se contentent de Jobs. Presque toutes les requêtes vont sur StartDate, la plupart d'entre elles incluent AccountId et certains des autres champs de comptabilité (nous avons des index sur eux). Les requêtes sont assez simples – la plus grande partie des plans d'exécution est la jointure pour JobSteps.

La priorité est la performance d'insertion. Une certaine latence (5 minutes environ) est tolérable pour que datatables apparaissent dans les requêtes, donc la réplication sur d'autres servers et l'exécution de requêtes hors de celles-ci sont certainement permises.

La search basée sur les GUID est très rare, à part de joindre JobSteps aux Jobs.

Configuration actuelle : aucun index clusterisé. Le seul qui semble être un candidat est StartDate. Mais, ça n'augmente pas parfaitement. Les travaux peuvent être insérés n'importe où dans une window de 3 heures après leur StartDate. Cela pourrait signifier qu'un million de lignes sont insérées dans un ordre qui n'est pas définitif.

La taille des données pour un Job 1 + 1 JobStepId, avec mes index actuels, est d'environ 500 octets.

Questions :

  • Est-ce un bon usage d'un tas?

  • Quel est l'effet de la mise en cluster sur StartDate, quand il est à peu près non-séquentiel pour ~ 2 heures / 1 million de lignes? Ma conjecture est que le ré-ordonnancement constant tuerait perf insertion.

  • Devrais-je simplement append des PK bigint juste pour avoir des keys plus petites et toujours en augmentation? (J'ai encore besoin des guids pour les searchs.)

J'ai lu les GUID comme PRIMARY KEYs et / ou la key de clustering , et il semblait suggérer que même l'invention d'une key permettrait d'économiser beaucoup d'espace sur d'autres index. De plus, certaines ressources suggèrent que les tas ont des problèmes de perf en général, mais je ne suis pas sûr que cela s'applique encore dans SQL 2008.

Et encore, oui, je vais essayer de tester et de mesurer le perf. J'essaie juste d'get des conseils ou des liens vers d'autres articles afin que je puisse prendre une décision plus éclairée sur les paths à considérer.

Oui, les tas ont des problèmes. Vos données vont logiquement se fragmenter partout dans le spectacle et ne peuvent pas être défragmentées simplement.

Imaginez-vous jeter tout votre directory téléphonique dans un seau, puis essayer de find "bob smith". Ou en utilisant un directory téléphonique conventionnel avec un index clusterisé sur le nom, le prénom.

L'overhead de maintenir l'index est sortingvial.

StartDate, à less d'être unique, n'est pas un bon choix. Un index clusterisé requirejs une unicité interne pour les index non clusterisés. S'il n'est pas déclaré unique, SQL Server appenda un "uniquificateur" de 4 octets.

Oui, j'utiliserais int ou bigint pour le rendre plus facile. Comme pour les GUID: voir les questions sur le côté droit de l'écran.

Modifier:

Remarque: PK et l'index cluster sont deux problèmes distincts, même si SQL Server par défaut rendra le cluster PK.

La fragmentation des tas n'est pas nécessairement la fin du monde. Il semble que vous numériserez rarement datatables, ce n'est donc pas la fin du monde.

Vos index non clusterisés sont les éléments qui auront un impact sur vos performances. Chacun aura besoin de stocker l'adresse de la ligne dans la table underlynig (soit un tas ou un index clusterisé). Idéalement, vos requêtes ne doivent jamais utiliser la table sous-jacente elle-même, car elle stocke toutes les informations nécessaires de manière idéale (y compris toutes les colonnes, de sorte que c'est un index de couverture).

Et oui, les trucs de Kimberly Tripp sont les meilleurs pour les index.

Rob

Comme votre propre search l'a montré, et comme tous les autres répondants l'ont mentionné, l'utilisation d'un GUID comme index clusterisé sur une table est une mauvaise idée.

Cependant, avoir un tas n'est pas vraiment un bon choix, car les tas ont d'autres problèmes, principalement liés à la fragmentation et à d'autres choses qui ne fonctionnent pas bien avec un tas.

Mon conseil sur les meilleures pratiques serait toujours le suivant:

  • utilisez une key primaire en cluster sur n'importe quelle table de données (sauf s'il s'agit d'une table temporaire ou d'une table utilisée pour le chargement en bloc)
  • essayez de vous assurer que la key groupée est une ID INTENTION ou une IDENTITÉ BIGINT

Je dirais que les avantages que vous obtenez en ajoutant un INT / BIGINT – même juste pour avoir un bon index clusterisé – l'emportent de loin sur les inconvénients que cela a (comme Kim Tripp l'explique également dans son blog que vous avez cité).

Marc

Comme une GUId est votre key primaire et étrangère, votre database devra toujours vérifier les contraintes sur chaque insertion dont vous aurez probablement besoin pour l'indexer. L'indexing d'un GUId n'est pas conseillée en raison de son caractère random. Par conséquent, je dirais absolument que vous devriez descendre la route bigint (probablement l'identité) pour votre key primaire et l'utiliser comme un index clusterisé.