Comment créer un index clusterisé sur une table de 100 Go

8

J'ai une table de tas qui prend environ 104 Go d'espace disque avec près de 3 milliards de lignes. J'essaie de créer un index cluster sur cette table dans la WeekEndingDatecolonne [ ]. J'ai environ 200 Go de libre dans le fichier de données et environ 280 Go de libre dans le tempdb.

J'ai essayé deux méthodes différentes. La première consistait à créer l'index directement sur la table avec la commande suivante:

CREATE CLUSTERED INDEX CX_WT_FOLD_HISTORY
ON WT_FOLD_HISTORY (WeekEndingDate ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = ON, 
IGNORE_DUP_KEY = OFF
, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, 
DATA_COMPRESSION = PAGE)

Je l'ai essayé à la fois avec SORT_IN_TEMPDB = ONet OFF. Lors de son utilisation, ONil a rempli le tempdb et avec OFFlui a rempli le lecteur de données.

Une autre méthode consistait à créer une nouvelle table vide avec l'index nécessaire, puis à insérer les enregistrements du tas dans la nouvelle table. Cela a également échoué après le remplissage du lecteur de données.

Toutes autres suggestions sur quoi faire. La plupart des choses que j'ai lues ont déclaré que j'aurais besoin d'environ 1,2 fois la taille de la table pour être utilisé comme espace de travail lors de la création de l'index. J'ai bien plus que ça et ça échoue toujours. Toute suggestion serait appréciée.

Voici ma structure de table de tas d'origine:

CREATE TABLE [dbo].[WT_FOLD_HISTORY](
[WeekEndingDate] [varchar](50) NULL,
[Division] [varchar](50) NULL,
[Store] [varchar](50) NULL,
[SKUNumber] [varchar](50) NULL,
[UPC] [varchar](50) NULL,
[SalesUnits] [varchar](50) NULL,
[SalesCost] [varchar](50) NULL,
[SalesRetail] [varchar](50) NULL,
[InventoryUnits] [varchar](50) NULL,
[InventoryCost] [varchar](50) NULL,
[InventoryRetail] [varchar](50) NULL,
[OnOrderUnits] [varchar](50) NULL,
[OnOrderCost] [varchar](50) NULL,
[OnOrderRetail] [varchar](50) NULL,
[ReceiptUnits] [varchar](50) NULL,
[ReceiptCost] [varchar](50) NULL,
[ReceiptRetail] [varchar](50) NULL,
[PermanentMarkdowns] [varchar](50) NULL,
[ReturnsToVendor] [varchar](50) NULL,
[POSMarkdowns] [varchar](50) NULL,
[TimeFK] [smallint] NULL,
[LocationFK] [int] NULL,
[ItemFK] [int] NULL
) ON [AcademySports_DataFG1]
user578849
la source
Lorsque vous effectuez l'approche "nouveau tableau, déplacer les lignes par lots", supprimez-vous les lignes du tableau d'origine lorsque vous les déplacez? Vous devrez peut-être faire de la gymnastique supplémentaire pour que le tas libère l'espace inutilisé lorsque vous supprimez des données.
AMtwo
Pourrait être intéressant de savoir pourquoi un index non clusterisé n'est pas acceptable dans ce cas; [oui, je suis conscient des différences / avantages des clusters par rapport aux non-clusters ... juste curieux de savoir pourquoi vous avez exclu un index non-cluster]; De plus, la table a-t-elle déjà des index non clusterisés en place et si oui, combien d'espace utilisent-ils? [vous vous demandez si la suppression d'index non cluster actuels pourrait libérer suffisamment d'espace pour créer l'index cluster?]
markp-fuso
Avez-vous essayé de créer l'index avec DATA_COMPRESSION=NONE? Si cela fonctionne, vous pouvez ensuite compresser.
Dan Guzman
nice question.i google it.and lire ce qu'ils ont dit dba.stackexchange.com/questions/11956/… ou stackoverflow.com/questions/2309889/… C'est la seule bonne réponse.
KumarHarsh
1
Pour être certain, pourriez-vous inclure le message d'erreur réel avec lequel il échoue?
RDFozz

Réponses:

3

Si vous avez un besoin d'espace disque à court terme, une option serait de:

  1. Réduisez temporairement tempdb, libérant autant d'espace sur ce disque que cela semble sûr.
  2. Créez un fichier de données secondaire pour la base de données dans laquelle se trouve la table sur le lecteur tempdb.
  3. Ajoutez l'index cluster à la table.
  4. Réduisez le fichier secondaire en migrant toutes les données hors de celui-ci.
  5. Supprimez le fichier secondaire.
  6. Assurez-vous que le fichier tempdb peut atteindre sa taille précédente.
  7. Reconstruisez les index dans la base de données de la table (la suppression du fichier secondaire aura provoqué une certaine fragmentation).

REMARQUE: comme d'autres l'ont suggéré, je ne ferais cela qu'après avoir supprimé temporairement des index non cluster de la table en question. Cela permettra en particulier l'ajout de l'index clusterisé, car les index non clusterisés devraient tous être reconstruits de toute façon (avec un index clusterisé en place, la clé d'index est utilisée pour localiser les lignes dans la table elle-même) .

C'est en fait un autre point - quelle est la largeur de la clé sur l'index clusterisé? Si vous disposez d'index non clusterisés et que la clé de l'index cluster est nettement plus large que le pointeur dans le segment de mémoire, les index non cluster consomment plus d'espace après la création de l'index cluster.

Si la clé de cluster se compose de plusieurs colonnes, ou même d'une grande colonne (par exemple, une varcharcolonne d'une longueur moyenne de 25 ou plus), vous souhaiterez peut-être envisager une clé de substitution à la place (généralement une valeur à augmentation monotone, pour de meilleures INSERTperformances.

RDFozz
la source
1

Ce qui remplit votre espace est votre méga-tri (vous essayez de trier tous vos 104 Go dans son ensemble), donc je pense qu'il peut être résolu en faisant un tri sur des portions plus petites. Je vous suggère de créer la nouvelle table en cluster et d'insérer les données en petits morceaux comme ceci:

declare @rowcount int = 1;
while @rowcount > 0
begin
  delete top (5000) 
  from your_heap with(tablock) 
      output deleted.field1, ..., deleted.fieldN 
      into new_clustered_table;
  set @rowcount = @@rowcount;
end; 

De cette façon, vous ne triez que 5000 lignes à la fois et le seul problème est que les sauts de page ne peuvent être évités car vous ne faites pas d'insertion triée. Ainsi, une fois terminé, la table new_clustered_table sera fragmentée, mais vous pourrez la reconstruire après.

sepupic
la source
Oui, vous avez raison, j'ai mis à jour ma réponse, mais ce n'était qu'une idée.
Seppic
0

Juste un petit conseil - pensez à supprimer tous les index non clusterisés (le cas échéant) sur ce segment avant d'essayer de créer un index clusterisé. Vous pouvez créer un script pour ces éléments non CI ainsi que les détails de leurs colonnes d'inclusion et les recréer ultérieurement avec ces définitions une fois que l'index clusterisé a été créé avec succès.

Channdeep Singh
la source