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

31

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 permettrait d'économiser de l'espace disque et des E / S disque car il n'y a pas d'index cluster à maintenir et la fragmentation supplémentaire ne serait pas un problème en raison des lectures très rares.

marc.d
la source
1
Parlez-vous de SQL Server?
a_horse_with_no_name
@a_horse_with_no_name oui, j'ai oublié de mentionner que sry
marc.d
Les tables de tas sont bonnes pour les tables avec des millions de lignes qui sont fortement touchées par les utilisateurs. L'inconvénient est qu'ils peuvent occuper beaucoup d'espace car les données sont stockées physiquement non triées. En outre, vous comptez sur vos index pour être à l'écoute de vos requêtes. J'ai travaillé dans des endroits qui n'utilisaient pas du tout d'index clusterisés en raison de problèmes de performances. Probablement en raison de mauvais choix d'index cluster, mais si vous utilisez simplement des tables de tas, vous n'avez pas à vous en soucier. Une meilleure solution serait d'utiliser l'édition d'entreprise du serveur SQL et de partitionner horizontalement la grande table. Mais si vous n'avez pas l'ent
Voir aussi stackoverflow.com/questions/1341393/… .
Jon of All Trades

Réponses:

22

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 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 aucun "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

gbn
la source
2
Il utilise généralement des tas pour deux choses distinctes. Tables de transfert et de travail ETL que j'utilise pour stocker temporairement des données lorsque l'ensemble est trop grand pour qu'une table temporaire fonctionne efficacement. Tous sont tronqués à la prochaine charge.
Zane
Bonne question d'ailleurs.
Zane
1
Un léger ajustement - si vous effectuez un SELECT INTO afin de créer une sauvegarde rapide d'une petite table avant d'apporter une modification, un segment de mémoire est créé par défaut. Je dirais que c'est une utilisation valable - mais ce n'est que du choix. Je voudrais me débarrasser de ce tas dès que je saurais que mon travail est terminé.
Brent Ozar
@BrentOzar: D'accord, je le fais tout le temps moi-même. L'esprit de ma réponse est "tables à long terme et persistantes" mais je
mettrai à
9

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 INTs 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.

Jon de tous les métiers
la source
5

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 les lectures ont donc 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 indice 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 supplémentaire d'une table organisée par index (table en cluster) sur certaines colonnes arbitraires par rapport à la possibilité de bcp dans un segment, de traiter les partitions OLAP, d'effectuer des requêtes d'analyse de table, puis de les supprimer 3 jours plus tard, cela signifie qu'il ne vaut tout simplement 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 ...

Phil Stephenson
la source