Come creare un indice cluster su una tabella da 100 GB


8

Ho una tabella heap che occupa circa 104 GB di spazio su disco con quasi 3 miliardi di righe. Sto cercando di creare un indice cluster su questa tabella nella WeekEndingDatecolonna [ ]. Ho circa 200 GB gratuiti nel file di dati e circa 280 GB gratuiti nel tempdb.

Ho provato due metodi diversi. Il primo era creare l'indice direttamente sulla tabella con il seguente comando:

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)

Ho provato entrambi con SORT_IN_TEMPDB = ONe OFF. Durante l'utilizzo ONha riempito il tempdb e con OFFesso ha riempito l'unità dati.

Un altro metodo consisteva nel creare una nuova tabella vuota con l'indice necessario e quindi inserire i record dall'heap nella nuova tabella. Anche questo non è riuscito dopo aver riempito l'unità dati.

Altri suggerimenti su cosa fare. La maggior parte delle cose che ho letto ha affermato che avrei bisogno di circa 1,2 volte la dimensione della tabella da utilizzare come spazio di lavoro durante la creazione dell'indice. Ho molto di più e continua a fallire. Tutti i suggerimenti sarebbero apprezzati.

Ecco la mia struttura originale della tabella heap:

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]

Quando fai l'approccio "nuova tabella, sposta le righe in batch", stai eliminando le righe nella tabella originale mentre le sposti? Potrebbe essere necessario fare ginnastica aggiuntiva per fare in modo che l'heap rilasci lo spazio inutilizzato mentre si eliminano i dati.
Due

Potrebbe essere interessante il motivo per cui un indice non cluster non è accettabile in questo caso; [sì, sono consapevole delle differenze / benefici del clustering rispetto al non cluster ... sono solo curioso di sapere perché hai escluso un indice non cluster]; inoltre, nella tabella sono già presenti indici non cluster e in caso affermativo, quanto spazio utilizzano? [chiedendosi se l'eliminazione di qualsiasi indice non cluster corrente potrebbe liberare spazio sufficiente per creare l'indice cluster?]
markp-fuso

Hai provato a creare l'indice con DATA_COMPRESSION=NONE? Se funziona, puoi comprimerlo in seguito.
Dan Guzman,

bello question.I google it.and leggere questo è quello che hanno detto dba.stackexchange.com/questions/11956/... o stackoverflow.com/questions/2309889/...~~V~~plural~~3rd Questa è la risposta unica corretta.
KumarHarsh,

1
Giusto per essere sicuri, potresti includere l'effettivo messaggio di errore con cui non riesce?
RDFozz,

Risposte:


3

Se hai una necessità a breve termine di spazio su disco, un'opzione sarebbe:

  1. Riduci temporaneamente tempdb, liberando tanto spazio su quell'unità quanto sembra sicuro.
  2. Creare un file di dati secondario per il DB in cui si trova la tabella nell'unità tempdb.
  3. Aggiungi l'indice cluster alla tabella.
  4. Riduci il file secondario migrando tutti i dati da esso.
  5. Rimuovi il file secondario.
  6. Assicurarsi che il file tempdb sia autorizzato a raggiungere le dimensioni precedenti.
  7. Ricostruisci gli indici nel DB della tabella (la rimozione del file secondario avrà causato una frammentazione).

NOTA: come altri hanno suggerito, lo farei solo dopo cose come la rimozione temporanea di indici non cluster dalla tabella in questione. Ciò in particolare consentirà l'aggiunta dell'indice cluster per andare più veloce, poiché gli indici non cluster dovrebbero comunque essere ricostruiti (con un indice cluster in atto, la chiave di indice viene utilizzata per individuare le righe nella tabella stessa) .

Questo è in realtà un altro punto: quanto è larga la chiave sull'indice cluster? Se si dispone di indici non cluster e la chiave sull'indice cluster è significativamente più ampia di quanto non fosse il puntatore nell'heap, gli indici non cluster consumeranno più spazio dopo la creazione dell'indice cluster.

Se la chiave del cluster è composta da più colonne o anche una colonna grande (ad esempio una varcharcolonna con una lunghezza media di 25 o più), è possibile prendere in considerazione una chiave surrogata (in genere un valore monotonicamente crescente, per INSERTprestazioni ottimali) .


1

Ciò che sta riempiendo il tuo spazio è il tuo mega-ordinamento (cerchi di ordinare tutti i tuoi 104Gb nel loro insieme), quindi penso che possa essere risolto facendo l'ordinamento su porzioni più piccole. Ti suggerisco di creare la nuova tabella cluster e inserire i dati in piccoli blocchi come questo:

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; 

In questo modo si ordinano solo 5000 righe alla volta e l'unico problema sono le divisioni di pagina che non possono essere evitate poiché non si effettua l'inserimento ordinato. Quindi, una volta terminato, new_clustered_table verrà frammentato ma dopo sarà possibile ricostruirlo.


Sì, hai ragione, ho aggiornato la mia risposta, ma era solo un'idea.
sepupic,

0

Solo un breve suggerimento: considera di eliminare tutti gli indici non cluster (se presenti) su questo heap prima di tentare di creare un indice cluster. È possibile eseguire lo script di quei non-CI insieme ai loro dettagli delle colonne include e crearli successivamente con quelle definizioni dopo aver creato correttamente l'indice cluster.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.