2009-08-17 6 views
4

OK. 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 tableaux:Uniqueidentifier PK: un tas SQL Server est-il le bon choix?

Emploi

  • JobID (PK, GUID, à l'extérieur généré)
  • StartDate (datetime2)
  • accountid
  • Plusieurs autres domaines de la comptabilité, principalement décimaux et bigints

JobSteps

  • JobStepID (PK, GUID, généré à l'extérieur)
  • JobID FK
  • StartDate
  • Plusieurs autres domaines de la comptabilité, principalement décimaux et bigints

Utilisation: Beaucoup d'inserts (centaines/seconde), généralement 1 JobStep par tâche. 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.

Effectuez ~ 10 requêtes/s par rapport aux données. 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 les données apparaissent dans les requêtes, donc la réplication vers d'autres serveurs et l'exécution de requêtes hors de celles-ci est certainement permise.

La recherche 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 tâches peuvent être insérées n'importe où dans une fenêtre 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 une bonne utilisation 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. Dois-je simplement ajouter des PK bigint simplement pour avoir des clés plus petites et toujours plus grandes?(Je encore besoin des guids pour les recherches.)

Je lis GUIDs as PRIMARY KEYs and/or the clustering key, et il semblait suggérer que même inventer une clé permettra d'économiser un espace considérable sur d'autres indices. En outre, 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 une fois, oui, je vais essayer de tester et mesurer la performance. J'essaie juste d'obtenir des conseils ou des liens vers d'autres articles afin que je puisse prendre une décision plus éclairée sur les chemins à considérer.

Répondre

5

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 que vous jetiez tout votre répertoire téléphonique dans un seau, puis que vous essayiez de trouver "bob smith". Ou en utilisant un répertoire téléphonique conventionnel avec un index clusterisé sur le nom, le prénom.

Le surdébit de maintenance de l'index est trivial. StartDate, à moins d'être unique, n'est pas un bon choix. Un index clusterisé requiert une unicité interne pour les index non clusterisés. S'il n'est pas déclaré unique, SQL Server ajoutera 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.

Edit:

Note, PK et l'index cluster sont 2 questions distinctes, même si par défaut est SQL Server faire le PK en cluster.

+1

Oui, je voulais vraiment éviter GUIDs comme clé en cluster, comme toutes les autres questions montrent. StartDate aurait besoin d'une identité supplémentaire. J'étais juste inquiet que l'insertion de dates de début essentiellement "aléatoires" sur une période de 2 heures pourrait signifier beaucoup de réorganisation ou quelque chose. Donc, en bref, allez ajouter un bigint PK pour que tout soit beau et groupé? – MichaelGG

+1

@MichaelGG: oui. c'est étroit, numérique, strictement monotone croissant, unique = bon index clusterisé – gbn

+0

A droite, je comprends qu'un int PK est beaucoup plus adapté qu'un guid. Ma question était de savoir si l'ajout d'une nouvelle colonne bigint juste pour avoir des index clusterisés, par opposition à la laisser comme un tas était une bonne idée. Il semble que ce soit le bon mouvement. – MichaelGG

1

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

+0

J'ai encore besoin du guid indexé, car j'ai besoin de faire des recherches occasionnelles dessus. Un index non cluster avec un facteur de remplissage inférieur devrait fonctionner ok, non? – MichaelGG

+0

Je ferais cet appel basé sur combien de fois vous avez besoin de faire vos recherches "occasionnelles". Si comme vous le dites, insérer la vitesse est la clé, alors moins d'index vous aideront, en particulier les plus complexes comme un GUId. Si vous faites une recherche GUId par semaine alors une analyse de table lente peut être acceptable en comparaison de maintenir l'index sur 100 inserts par seconde .... Je vous suggère de profiler cela pour être sûr cependant. –

+0

OK - fera l'affaire. Merci! – MichaelGG

3

La fragmentation de tas n'est pas nécessairement la fin du monde. Il semble que vous numériserez rarement les données, 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 n'ont jamais besoin d'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 qu'il s'agit d'un index de couverture).

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

Rob

+0

Certaines des requêtes sont des agrégats et peuvent être traitées à partir d'un index uniquement. Mais beaucoup ont besoin de retourner presque chaque colonne des deux tables. Ai-je compris l'information de Kimberly qu'en passant de guid à bigint PK en cluster, je vais économiser beaucoup d'espace sur mes autres index? – MichaelGG

+0

La modification de votre structure (ou de ce qui se trouve dans un index clusterisé) affecte tous les index non clusterisés de la table. Je suggère que laisser vos données comme un tas serait le chemin à parcourir. Passez votre temps à obtenir vos index non clusterisés. Et en fait, vous pouvez même trouver que les index non clusterisés avec beaucoup de colonnes incluses fonctionnent mieux que d'obtenir un index clusterisé. Mais oui, un bigint (8 octets) est plus petit qu'un guid (16 octets), et cela apparaît sur chaque rangée de feuilles de votre NCIX. –

+0

Aussi ... puisque vous ne mettez pas à jour, les plus grandes différences entre le laisser comme un tas et mettre une clé de substitution sont: 1. Introduire un nouveau champ se développera chaque ligne, vous donnant la fragmentation dont vous n'avez pas besoin. 2. Votre table devra être reconstruite, et les NCIX avec elle. 3. Les NCIX seront légèrement plus petits, l''adresse de ligne' se sera réduite un peu. Mais à la fin de la journée, obtenez vos NCIX correctement et vous ne devriez pas avoir à se soucier de ce que votre tas sous-jacent/CIX ressemble. –

2

Comme vos propres recherches ont montré, et comme tous les autres answerers ont mentionné, en utilisant un GUID comme l'index cluster 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 des meilleures pratiques serait toujours ceci:

  • utilisent une clé primaire, cluster sur une table de données (à moins d'une table temporaire ou une table utilisée pour chargement en vrac)
  • essayer pour vous assurer que la clé cluster est une identité INT ou BIGINT IDENTITÉ

Je dirais que les avantages que vous obtenez en ajoutant un INT/BIGINT - même juste pour le plaisir d'avoir un bon index ordonné en clusters - l'emportent largement sur les inconvénients cela a (comme Kim Tripp se dispute aussi dans son blog po st vous avez cité).

Marc

Questions connexes