Qual è il modo più veloce per inserire un numero elevato di righe?


27

Ho un database in cui carico i file in una tabella di gestione temporanea, da questa tabella di gestione temporanea ho 1-2 join per risolvere alcune chiavi esterne e quindi inserire queste righe nella tabella finale (che ha una partizione al mese). Ho circa 3,4 miliardi di righe per tre mesi di dati.

Qual è il modo più veloce per ottenere queste righe dalla messa in scena nel tavolo finale? Attività Flusso di dati SSIS (che utilizza una vista come origine e ha un caricamento rapido attivo) o un comando Inserisci INTO SELECT ....? Ho provato l'attività Flusso di dati e riesco a ottenere circa 1 miliardo di righe in circa 5 ore (8 core / 192 GB di RAM sul server), il che mi sembra molto lento.


1
Le partizioni sono su filegroup separati (e si trovano su quei filegroup su diversi dischi fisici)?
Aaron Bertrand

3
Una risorsa davvero valida La Guida alle prestazioni di caricamento dei dati . Questo risolve molte ottimizzazioni delle prestazioni che è possibile eseguire, ad esempio Abilitazione di TF610 , Uso di BCP OUT / IN, SSIS ecc. Devi solo seguire i consigli e testarli nel tuo ambiente.
Kin Shah,

@Aaron sì, al mese un filegroup, 12 san lun sono allegati, quindi tutti jan vanno su un lun ecc. Non sono sicuro di quanti dischi al lun, ma dovrebbero essere in abbondanza.
nojetlag,

Sì, intendevo davvero "set di dischi" e probabilmente avrei potuto menzionare anche i controller, che possono essere saturi.
Aaron Bertrand

@Kin ha dato un'occhiata alla guida ma sembra obsoleto, "La destinazione SQL Server è il modo più veloce per caricare in blocco i dati da un flusso di dati di Integration Services a SQL Server. Questa destinazione supporta tutte le opzioni di caricamento in blocco di SQL Server - tranne ROWS_PER_BATCH ". e in SSIS 2012 raccomandano la destinazione OLE DB per prestazioni migliori.
nojetlag,

Risposte:


25

Un approccio comune:

  1. Disabilita / elimina indici / vincoli sulla tabella di destinazione.
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. Con il credito a JNK, ovviamente, puoi fare quanto sopra in lotti di nrighe, il che può ridurre lo sforzo sul registro delle transazioni e, naturalmente, significa che se un batch non funziona, devi solo iniziare da quel batch. Ho scritto un blog al riguardo (mentre in riferimento alle eliminazioni, si applicano gli stessi concetti di base) qui: http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. Riattivare / ricreare indici / vincoli sulla tabella di destinazione (e forse è possibile rinviarne alcuni, se non sono necessari per tutte le operazioni, ed è più importante ottenere rapidamente i dati di base online).

Se le tue partizioni sono fisiche e non solo logiche, potresti guadagnare un po 'di tempo facendo in modo che processi diversi popolino diverse partizioni contemporaneamente (ovviamente questo significa che non puoi usare TABLOCK/ TABLOCKX). Ciò presuppone che l'origine sia adatta anche a più processi selezionando senza sovrapposizioni / blocchi ecc. E rendendo ancora più lento quel lato dell'operazione (suggerimento: creare un indice cluster sull'origine adatto allo schema di partizionamento sulla destinazione).

Puoi anche considerare qualcosa di molto più primitivo, come BCP OUT/BCP IN .

Non so che vorrei saltare a SSIS per aiutare con questo. Probabilmente ci sono alcune efficienze lì, ma non so che lo sforzo giustifica i risparmi.


2
Non rilasciare gli indici alla cieca (specialmente l'indice cluster) se i dati non sono ordinati. Eliminare l'indice e aspettarsi di ricreare un indice cluster può essere un errore enorme perché può costare sia un enorme spazio su disco che un enorme periodo di tempo. Non sono il primo a sperimentare un simile errore. Guarda la descrizione del "Piano B" in questo articolo sqlmag.com/t-sql/… . L'autore ha avuto lo stesso problema.
jyao,

10

Guardando il tuo problema dal punto di vista SSIS, ritengo che il motivo per cui questo potrebbe aver impiegato così tanto tempo sia che non hai avuto il batching. Questo può portare a troppe righe che riempiono la pipeline SSIS e di conseguenza possono ostacolare le prestazioni del SSIS. Quello che devi fare è modificare le tue righe per impostazione batch e possibilmente la dimensione massima di commit dell'inserimento. Ora, anche ciò che imposti dipenderà dalla quantità di memoria disponibile per il tuo server SSIS? Qual è la velocità del disco dell'istanza di SQL Server? Il modo migliore per farlo è test. Consente ad esempio di usare 10.000. Questo invierà un batch al server 10.000 alla volta, evitando così il riempimento eccessivo della pipeline e contribuirà a eseguire questo processo più velocemente. Queste impostazioni sono configurate nella destinazione OLEDB.

Destinazione OLEDB

Se si tratta di un problema, puoi anche aggiungere un'attività di esecuzione SQL prima e dopo, come suggerisce @AaronBertrand e rimuovere / aggiungere nuovamente gli indici o i vincoli alla tabella.


1
C'è una domanda eccellente su ciò che "caricamento rapido" comporta altrove su DBA.SE: dba.stackexchange.com/questions/141430/… .
Jon of All Trades,
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.