Migliora la velocità di ricostruzione dell'indice su SQL Server


9

Sto importando una grande quantità di dati in un database vuoto e prima di iniziare ho disabilitato tutti gli indici non cluster non univoci per vedere se potevo migliorare le prestazioni dell'importazione.

Ora voglio riattivare gli indici e mi chiedo se c'è qualcosa che posso fare per ottimizzarlo.

Ci sono> 100 tabelle e quasi 2.000 indici da ricostruire. Il database ha dimensioni di 200 GB.

La sezione chiave dello script che sto eseguendo è questa:

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

Ho considerato l'impostazione ONLINE = OFF per l'istruzione alter index, ma poiché gli indici iniziano disabilitati non ero sicuro che questa impostazione avrebbe avuto alcun effetto. Ho anche considerato di impostare SORT_IN_TEMPDB = ON, ma poiché i file tempdb si trovano sulla stessa unità dei file .mdf dei database, ho pensato che non ci sarebbe stato alcun vantaggio nel farlo.

Durante l'esecuzione dello script di ricostruzione ho notato che ho molti tipi di attesa di CXPACKET. Non capisco davvero perché sarebbe o se è un problema che dovrei cercare di affrontare.

Un ultimo punto che può essere rilevante: il mio intero server è attualmente inattivo diverso da questa importazione di dati nel database. Non ci sono altre attività dell'utente da considerare o di cui preoccuparsi; la mia unica preoccupazione è importare i dati nel database nel più breve tempo possibile.


3
Quando dici che la tua unica preoccupazione è il tempo di importazione, intendi il tempo che intercorre tra l'inizio e la fine della riattivazione degli indici? In tal caso, dovresti semplicemente lasciare gli indici abilitati durante l'importazione. 2.000 indici per dati da 200 GB mi sembrano un sacco di indici. Forse dovresti guardare i DMV di utilizzo dell'indice per vedere se ce ne sono alcuni che potrebbero essere rimossi.
Max Vernon,

1
Solo per chiarire, devi fare la stessa importazione da 200 GB ripetutamente, e non solo una volta?
Jon Seigel,

1
Devo eseguire l'importazione solo una volta, ma come parte di un processo più ampio con un intervallo di tempo limitato, quindi sto attualmente testando quel processo per farlo rientrare in quella finestra. @MaxVernon Sembra che tu abbia ragione nel lasciare gli indici abilitati nel modo più veloce, anche se sono sorpreso mentre leggevo che normalmente era più veloce disabilitare gli indici, importare i dati, quindi riattivare gli indici. Questo è un database di terze parti, quindi non è possibile rimuovere gli indici o modificarlo in altro modo.
paul

3
Va bene. Informazioni sulle CXPACKETattese: l'indice si ricostruisce eseguendo la scansione degli indici (anche l'indice in fase di ricostruzione ) e tali scansioni possono utilizzare il parallelismo. Non dovresti preoccuparti di quelle attese - il parallelismo probabilmente sta aiutando.
Jon Seigel,

Risposte:


10

Il raggiungimento di prestazioni di importazione ottimali in questo scenario richiede tre cose:

  1. Inserti della tabella di base con registrazione minima
  2. Build di indici non cluster minimamente registrati
  3. Evitare letture fisiche

Registrazione minima

Il raggiungimento di inserimenti con registrazione minima in una tabella cluster vuota senza indici non cluster richiede:

  1. Utilizzo dei modelli di recupero del database SIMPLEoBULK_LOGGED
  2. Specificare un blocco tabella e input ordinati (ad es. TABLOCKE ORDERsuggerimenti)

Nota a margine:

È anche possibile ottenere inserimenti con registrazione minima in una tabella di cluster con indici non cluster purché sia ​​abilitato il flag di traccia 610. Il fatto che gli inserti di indice non cluster siano registrati minimamente o meno dipende dal piano di query selezionato da Query Optimizer.

Se il piano di query utilizza un iteratore separato per l'indice non cluster e l'iteratore ha la DMLRequestSortproprietà impostata su true, gli inserimenti dell'indice non cluster verranno minimamente registrati, a condizione che siano soddisfatte le altre condizioni menzionate in precedenza.

Creazione di indici non cluster separatamente

I vantaggi di farlo sono:

  1. Gli inserti di indice cluster possono essere minimamente registrati senza abilitare TF 610
  2. CREATE INDEX viene minimamente registrato se il modello di recupero non lo è FULL

Evitare letture fisiche

Idealmente, i dati da importare verranno archiviati su una macchina separata, o almeno su una memoria fisica separata da quella utilizzata per ospitare il database.

Il server di database deve disporre di memoria sufficiente per contenere la tabella di base più grande nella cache, con spazio sufficiente per le operazioni di ordinamento necessarie durante la creazione di indici non cluster.

Un buon modello consiste nel caricare rapidamente la tabella di base (caricamento dell'indice cluster con registrazione minima) e quindi nel creare tutti gli indici non cluster per quella tabella mentre le sue pagine di dati sono ancora memorizzate nella cache.

La domanda delinea un processo in base al quale le tabelle di base vengono caricate per prime, quindi vengono creati gli indici non cluster. La definizione del cursore non utilizza una ORDER BYclausola per raggruppare almeno le build dell'indice non cluster sulla stessa tabella.

Il probabile risultato è che le pagine di dati per diverse tabelle vengono ripetutamente lette nella cache e quindi eliminate quando gli indici non cluster vengono creati in un ordine non deterministico.

Il costo delle letture fisiche ripetute domina completamente i vantaggi della registrazione minima ottenuta costruendo separatamente indici non cluster. Questo spiega perché hai scoperto che il caricamento di tabelle con indici esistenti è più rapido (perché tutti gli indici non cluster per una determinata tabella vengono mantenuti prima di passare alla tabella successiva).

Sommario

Il processo di importazione dovrebbe essere rielaborato per caricare in blocco una tabella alla volta. Ciò significa caricare la tabella e creare tutti gli indici non cluster prima di passare a quello successivo. L'istanza di SQL Server dovrebbe disporre di memoria sufficiente per contenere la tabella più grande ed eseguire contemporaneamente il più grande ordinamento dell'indice non cluster.

Si potrebbe anche provare ad abilitare TF 610 prima di caricare i dati in tabelle con gli indici non cluster già in atto. Questo di solito non è veloce come il metodo precedente, ma potrebbe essere abbastanza veloce.

Vedere di seguito per ulteriori informazioni:

La guida alle prestazioni di caricamento dei dati

Operazioni che possono essere minimamente registrate

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.