Qual è la dimensione del batch consigliata per SqlBulkCopy?


87

A cosa serve la dimensione del batch consigliata SqlBulkCopy? Sto cercando una formula generale da utilizzare come punto di partenza per l'ottimizzazione delle prestazioni.

Risposte:


97

Ho un'utilità di importazione che si trova sullo stesso server fisico della mia istanza di SQL Server. Utilizzando un custom IDataReader, analizza i file flat e li inserisce in un database utilizzando SQLBulkCopy. Un file tipico ha circa 6 milioni di righe qualificate, con una media di 5 colonne di testo decimale e breve, circa 30 byte per riga.

Alla luce di questo scenario, ho riscontrato che una dimensione batch di 5.000 è il miglior compromesso tra velocità e consumo di memoria. Ho iniziato con 500 e ho sperimentato con più grandi. Ho scoperto che 5000 sono in media 2,5 volte più veloci di 500. L'inserimento di 6 milioni di righe richiede circa 30 secondi con una dimensione del batch di 5.000 e circa 80 secondi con una dimensione del batch di 500.

10.000 non erano misurabilmente più veloci. Il passaggio a 50.000 ha migliorato la velocità di alcuni punti percentuali ma non valeva la pena aumentare il carico sul server. Oltre i 50.000 non hanno mostrato miglioramenti nella velocità.

Questa non è una formula, ma è un altro punto dati da utilizzare.


3
Una cosa da considerare è se la tabella è vuota e ha indici. In questi casi potresti voler caricare tutto in un batch come menzionato qui: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "Se importi in blocco i dati in una tabella vuota con indici e si specifica la dimensione del batch, la tabella diventa non vuota dopo il primo batch. A partire dal secondo batch, i dati vengono registrati completamente. Per le tabelle indicizzate vuote, valutare la possibilità di eseguire l'importazione in blocco in un singolo batch. "
Sal

SqlBulkCopy trasmette i dati dall'origine (ad esempio DataTable) a Sql, quindi quale "aumento del carico sul server" ha su un batch di grandi dimensioni? (es. 50.000)
BornToCode

29

Questo è un problema che ho anche esaminato per un po 'di tempo. Sto cercando di ottimizzare l'importazione di file CSV di grandi dimensioni (16+ GB, 65+ milioni di record e in crescita) in un database SQL Server 2005 utilizzando un'applicazione console C # (.Net 2.0). Come Jeremy ha già sottolineato , sarà necessario eseguire alcune regolazioni per le circostanze particolari, ma ti consiglio di avere una dimensione del lotto iniziale di 500 e di testare i valori sia sopra che sotto questo.

Ho ricevuto la raccomandazione di testare valori compresi tra 100 e 1000 per la dimensione del batch da questo post del forum MSDN ed ero scettico. Ma quando ho testato batch di dimensioni comprese tra 100 e 10.000, ho scoperto che 500 era il valore ottimale per la mia applicazione. Anche il valore 500 per SqlBulkCopy.BatchSizeè consigliato qui .

Per ottimizzare ulteriormente l'operazione SqlBulkCopy, consulta questo consiglio MSDN ; Trovo che l'utilizzo di SqlBulkCopyOptions.TableLock aiuti a ridurre i tempi di caricamento.


Ritengo che l'esecuzione del comando di copia di massa nel server stesso sarebbe probabilmente più veloce.
Capitano Kenpachi

16

Come altri hanno affermato, dipende dall'ambiente in particolare dal volume delle righe e dalla latenza di rete.

Personalmente, inizierei impostando la BatchSizeproprietà su 1000 righe e vedrei come funziona. Se funziona, continuo a raddoppiare il numero di righe (ad esempio a 2000, 4000, ecc.) Finché non ottengo un timeout.

Altrimenti, se si verifica un timeout a 1000, riduco il numero di righe della metà (es. 500) finché non funziona.

In ogni caso, continuo a raddoppiare (in caso di successo) o dimezzare (se fallito) la differenza tra ciascuna delle ultime due dimensioni di lotto tentate fino a trovare un punto ottimale.

L'altro fattore da considerare è il tempo necessario per copiare un singolo batch di righe. I timeout si verificheranno se il batch di righe da copiare supera la BulkCopyTimeoutproprietà che per impostazione predefinita è di 30 secondi. Potresti provare a raddoppiare la BulkCopyTimeoutproprietà a 60 secondi. Ciò consente un periodo di tempo più lungo per la copia di un set più ampio di righe batch. Ad esempio, un batch di 50.000 righe potrebbe richiedere circa 40 secondi superando il limite di tempo di 30 secondi, quindi aumentarlo fino a 60 secondi potrebbe aiutare con le prestazioni.


4

Tutto dipende dalla tua implementazione.

Che tipo di velocità puoi aspettarti sulla tua rete? Lo stai usando in Forms o ASP.Net? Hai bisogno di avvisare l'utente dei progressi? Qual è la dimensione del lavoro totale?

Nella mia esperienza, l'esecuzione di copie di massa senza una dimensione batch specificata causerà problemi di timeout. Mi piace iniziare con qualcosa come 1000 record e fare alcuni aggiustamenti da lì.


Velocità: varia, WebForm: sì, ASP.NET: sì, tabelle larghe: sì, tabelle strette, sì. Migliaia di righe: sì. Milioni di righe: sì. Se riesci a pensare a uno scenario, probabilmente lo sto facendo.
Jonathan Allen

1
Allora devo attenermi alla mia risposta precedente. Non credo che ci sia una pallottola d'argento.
Jeremy

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.