Considérations majeures
Je vois un avantage important pour les tas et un pour les tables en cluster, plus une troisième considération qui peut aller dans les deux sens.
Un tas vous permet d'économiser une couche d'indirection. Les index contiennent des ID de ligne pointant directement (enfin, pas vraiment, mais aussi directement que possible) vers un emplacement de disque. Ainsi, une recherche d'index sur un tas devrait coûter environ la moitié d'une recherche d'index non cluster sur une table cluster.
Un index clusterisé est trié, en soi, grâce à un index (presque) gratuit. Étant donné que l'index de clustering se reflète dans l'ordre physique des données, il occupe relativement peu d'espace au-dessus des données réelles elles-mêmes, que vous devez bien sûr stocker de toute façon. Parce qu'il est ordonné physiquement, une analyse de plage par rapport à cet index peut rechercher le point de départ, puis se rapprocher très efficacement du point final.
Les indices sur les tas font référence aux RID, qui sont de 64 bits. Comme mentionné, les index non clusterisés sur une table clusterisée font référence à la clé de clustering, qui peut être plus petite (32 bits INT
), identique (64 bits BIGINT
) ou plus grande (48 bits DATETIME2()
plus 32 bits INT
, ou un GUID 128 bits). De toute évidence, une référence plus large donne des indices plus grands et plus chers.
Espace requis
Avec ces deux tableaux:
CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)
CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)
... chacun contenant 8,7 millions d'enregistrements, l'espace requis était de 150 Mo pour les données des deux; 120 Mo pour les indices de la table en cluster, 310 Mo pour les indices de la table non en cluster. Cela reflète que l'index clusterisé est plus étroit qu'un RID, et que l'index clustering est principalement un «billet de faveur». Sans les index uniques ID2
, l'espace d'index requis tombe à 155 Mo pour la table non en cluster (la moitié, comme vous vous en doutez) mais à seulement 150 Ko pour le PK en cluster - presque rien.
Ainsi, un index non clusterisé d'un champ 32 bits dans une table en cluster avec un index 32 bits (total 64 bits, nominalement) a pris 120 Mo, tandis qu'un index d'un champ 32 bits dans un tas avec un 64 bits Le RID (96 bits au total, nominalement) a pris 155 Mo, un peu moins que l'augmentation de 50% que l'on pourrait naïvement espérer passer de clés de 64 bits à 96 bits, mais bien sûr, il y a des frais généraux qui réduisent la différence effective de taille.
Le remplissage des deux tables et la création de leurs indices ont pris le même temps pour chaque table. En exécutant des tests simples impliquant des analyses ou des recherches, je n'ai trouvé aucune différence de performance matérielle entre les tables, ce qui correspond au livre blanc de Microsoft qui gbn a lié utilement. Ledit document montre une différence significative pour un accès hautement simultané; Je ne sais pas pourquoi cela se produit, j'espère que quelqu'un avec plus d'expérience que moi avec les systèmes OLTP à haut volume pourra nous le dire.
L'ajout d'environ 40 octets de données aléatoires de longueur variable n'a pas sensiblement modifié cette équivalence. Le remplacement des INT
s par des UUID larges n'a pas non plus (chaque tableau a été ralenti à peu près dans la même mesure). Votre kilométrage peut varier, mais dans la plupart des cas si un indice est disponible est plus important que ce genre.
Morceaux
Faire une analyse de plage par rapport à un index non clusterisé - soit parce que la table est un segment de mémoire ou que l'index n'est pas l'index clusterisé - implique l'analyse de l'index, puis une recherche sur la table pour chaque hit. Cela peut être très coûteux, il est donc parfois moins cher de simplement scanner la table. Vous pouvez cependant contourner ce problème avec un indice de couverture. Cela s'applique que vous ayez groupé votre table ou non.
Comme l'a souligné @gbn, il n'y a pas de moyen simple de compacter un tas. Cependant, si votre table augmente progressivement au fil du temps - un cas très courant - il y aura peu de gaspillage car l'espace libéré par les suppressions sera rempli par de nouvelles données.
Plusieurs des discussions entre tas et tables en cluster que j'ai vues font un curieux argument de paille selon lequel un tas sans index est inférieur à une table en cluster en ce qu'il nécessite toujours une analyse de table. C'est certainement vrai, mais la comparaison la plus significative est «une grande table en cluster bien indexée» vs «un grand tas bien indexé». Si votre table est très petite ou que vous allez toujours effectuer des analyses de table, alors peu importe que vous la regroupiez ou non.
Étant donné que chaque index d'une table en cluster fait référence à l'index de clustering, ils sont en fait tous des indices de couverture. Une requête qui fait référence à une colonne indexée et aux colonnes de clustering peut effectuer une analyse d'index sans aucune recherche de table. Cela n'est généralement pas utile si votre index de clustering est une clé synthétique, mais s'il s'agit d'une clé métier que vous devez récupérer de toute façon, c'est une fonctionnalité intéressante.
TL; DR
Je suis un type d'entrepôt de données, pas un expert OLTP. Pour les tables de faits, j'utilise presque toujours un index de clustering sur le champ qui est généralement susceptible d'avoir besoin d'analyses de plage, généralement un champ de date. Pour les tables de dimension, je fais un cluster sur le PK, il est donc pré-trié pour les jointures de fusion avec les tables de faits.
Il existe plusieurs raisons d'utiliser des indices de clustering, mais si aucune de ces raisons ne s'applique, la surcharge peut ne pas valoir la peine. Je soupçonne qu'il y a beaucoup de «nous l'avons toujours fait de cette façon» et «c'est juste la meilleure pratique» derrière les personnes qui utilisent des index clusterisés universellement. Essayez à la fois avec vos données et votre charge et voyez ce qui fonctionne le mieux.