web-dev-qa-db-fra.com

Quels sont les scénarios d'utilisation valides pour les tables HEAP?

Je fais actuellement quelques importations de données dans un système hérité et j'ai découvert que ce système n'utilise pas un seul index clusterisé. Une recherche rapide sur Google m'a fait découvrir le concept des tables HEAP et maintenant je suis curieux de savoir dans quels scénarios d'utilisation une table HEAP devrait être préférée à une table en cluster?

Pour autant que je sache, une table HEAP ne serait utile que pour les tables d'audit et/ou lorsque les insertions se produisent beaucoup plus souvent que les sélections. Cela économiserait de l'espace disque et des E/S disque car il n'y a pas d'index clusterisé à maintenir et la fragmentation supplémentaire ne serait pas un problème en raison des lectures très rares.

31
marc.d

Les seules utilisations valides sont pour

  • tables intermédiaires utilisées dans les processus d'importation/exportation/ETL.
  • sauvegarde ad hoc, temporaire et à court terme des tables à l'aide de SELECT * INTO..

Les tables intermédiaires sont généralement assez plates et tronquées avant/après utilisation.

Notez qu'un index clusterisé est généralement peu petit par rapport à la taille des données: les données sont le niveau le plus bas de la structure d'index.

Les tables de tas ont également des problèmes. Au moins ceux-ci:

  • ne peut pas être défragmenté pour réduire l'espace sur le disque. Cela est important car les pages de données utilisées seront dispersées dans le MDF par exemple, car les données n'ont pas d '"ordre" à partir de l'index clusterisé
  • l'index non clusterisé pointe désormais vers la ligne, pas l'entrée d'index cluster. Cela affecte les performances: Besoin d'atteindre les données via un index cluster avec un index non cluster

Regarde aussi

22
gbn

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 est reflété dans l'ordre physique des données, il prend 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, un balayage de plage par rapport à cet index peut rechercher le point de départ, puis le Zip jusqu'au point d'arrivée très efficacement.

  • 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 (un INT 32 bits), la même (un BIGINT 64 bits), ou plus grand (une DATETIME2() de 48 bits plus un INT de 32 bits, ou un GUID de 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 indices uniques sur ID2, l'espace d'indexation requis tombe à 155 Mo pour la table non clusterisée (la moitié, comme vous vous en doutez) mais seulement 150 KO pour le cluster PK - 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 des systèmes à haut volume OLTP peut nous le dire.

L'ajout de ~ 40 octets de données aléatoires de longueur variable n'a pas sensiblement modifié cette équivalence. Le remplacement des INT par des UUID larges n'a pas non plus (chaque table a été ralentie à peu près dans la même mesure). Votre kilométrage peut varier, mais dans la plupart des cas si un index est disponible est plus important que quel type.

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, cela n'a pas beaucoup d'importance si vous la regroupez 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 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 en OLTP. Pour les tables de faits, j'utilise presque toujours un index de clustering sur le terrain qui est généralement susceptible d'avoir besoin d'analyses de plage, généralement un champ de date. Pour tables de dimension Je fais un cluster sur le PK donc il est 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 être utile. 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 gens qui utilisent les index clusterisés universellement. Essayez les deux avec vos données et vos chargez et voyez ce qui fonctionne le mieux.

9
Jon of All Trades

Je pense que dire "La seule utilisation valide est pour les tables de transfert utilisées dans les processus d'import/export/ETL" est pour le moins un peu restrictif. Vous devez prendre le cas d'utilisation attendu d'un système donné, puis choisir en fonction des mérites des tas ou des tables organisées par index (je sais, un terme Oracle mais il le décrit bien).

Notre entrepôt charge environ 1,5 milliard de lignes par jour et doit prendre en charge les écritures et les traitements ainsi que les lectures hautement simultanés. Le magasin relationnel prend en charge une base de données OLAP et, par conséquent, les lectures ont tendance à être principalement des analyses de table. Les rapports et les flux en aval qui sont générés ne sont généralement pas suffisamment sélectifs pour qu'un index soit utile. le système prend en charge une fenêtre coulissante de données et donc une fois qu'une table est chargée, nous y écrivons rarement à nouveau et étant donné la mise en œuvre plutôt médiocre du partitionnement de table nécessitant des verrous Sch-M pour les fractionnements, les commutateurs et les fusions par rapport aux verrous Sch-S pour les lectures, etc., le système a dû utiliser de nombreuses tables, bien que nous ayons aussi quelques tables partitionnées. L'utilisation de nombreuses tables facilite la segmentation des données et les cycles de nettoyage tout en réduisant les conflits.

En tant que tel, la surcharge ajoutée d'une table organisée par index (table en cluster) sur certaines colonnes arbitraires par rapport à la possibilité de bcp dans un tas, traiter les partitions OLAP, effectuer certaines requêtes d'analyse de table puis 3 jours plus tard, cela signifie que cela n'en vaut pas la peine. Notez que dans notre cas, les données proviennent d'un grand cluster de grille, il n'y a donc pas d'ordre dans les données, donc l'insertion dans une table avec un index cluster pourrait introduire d'autres problèmes tels que les "points chauds" et les sauts de page, etc.

De plus, je pense que l'argument selon lequel les pages sont dispersées est un peu fallacieux. Les index clusterisés peuvent également voir leurs pages dispersées dans le fichier. C'est juste qu'après réindexation (en supposant plus de 1000 pages), cela peut être mieux qu'un tas, mais vous avez également dû réindexer aussi.

Il est également possible d'économiser de l'espace en utilisant des colonnes éparses et la compression si cela est un problème. Il est vrai que dans certains cas, les sélections sur une table avec un index cluster peuvent être plus rapides, mais vous devez peser cela avec les ressources nécessaires pour le charger et le maintenir.

[Modifier] Je devrais probablement préciser que seules nos tables de faits non partitionnées sont des tas. Les tables partitionnées et les tables de dimension ont toutes des index clusterisés pour prendre en charge des recherches efficaces, etc. [Edit2] Corrigé de 2,5 milliards à 1,5 milliard. Tut, ces deux nombres étant côte à côte. Que se passe-t-il lors de la saisie des réponses sur un téléphone, je suppose ...

5
Phil Stephenson