2011-01-10 4 views
5

Dato: SQL Server 2008 R2. Chiudere alcuni dischi di velocità. Registra i dischi in ritardo.Ottimizzazione delle massicce prestazioni dell'inserto ...?

Obbligatorio: MOLTISSIMO MOLTO LOTTO di inserti. Come 10.000 a 30.000 righe in una tabella semplice con due indici al secondo. Gli inserti hanno un ordine intrinseco e non si ripeteranno, in quanto tale ordine di inserti non deve essere mantenuto a breve termine (cioè più inserimenti paralleli sono ok).

Finora: accumulo di dati in una coda. Regolarmente (threadpool asincrono) svuota fino a 1024 voci in un elemento di lavoro che viene messo in coda. Threadpool (classe personalizzata) ha 32 possibili thread. Apre 32 connessioni.

Problema: le prestazioni sono disattivate di un fattore di 300 .... vengono inserite solo 100-150 righe al secondo. Il tempo di attesa del registro è pari al 40% - 45% del tempo di elaborazione (ms al secondo) nel server SQL. Il carico della CPU del server è basso (dal 4% al 5% circa).

Non utilizzabile: inserto di massa. I dati devono essere scritti il ​​più possibile in tempo reale sul disco. Questo è praticamente un processo archivl di dati che attraversano il sistema, ma ci sono query che richiedono l'accesso ai dati regolarmente. Potrei provare a scaricarli su disco e utilizzando il caricamento collettivo 1-2 volte al secondo .... proveremo.

Qualcuno un'idea intelligente? Il mio prossimo passo è spostare il log su un set di dischi veloci (128 gb ssd moderno) e vedere cosa succede allora. Il significativo aumento delle prestazioni probabilmente farà cose abbastanza diverse. Ma anche allora ... la domanda è se/cosa sia fattibile.

Quindi, si prega di accendere le idee intelligenti.

+3

hai mai ottenere una risoluzione finale a questo? – Carth

risposta

4

Ok, me stesso. Dare una prova a SqlBulkCopy, eseguire il batching fino a 65536 voci e svuotarle ogni secondo in modo asincrono. Riferirà sui guadagni.

+3

Il risultato è 75.000 record al secondo utilizzando 3 thread. – TomTom

+0

Wow, è abbastanza impressionante, bel lavoro! –

3

Sto passando esattamente lo stesso problema qui, quindi seguirò i passaggi che sto prendendo per migliorare le mie prestazioni.

  • separato il registro e il file dbf su diversi set mandrino
  • Usa il recupero di base
  • lei non ha citato i requisiti di indicizzazione a parte il fatto che l'ordine degli inserti non è importante - in questo non dovrebbero essere usati indici clusterizzati su qualcosa di diverso da una colonna di identità.
  • avvia nuovamente il ridimensionamento della concorrenza da 1 e si interrompe quando la performance si appiattisce; qualsiasi cosa potrebbe danneggiare le prestazioni.
  • invece di passare al disco in bcp e, poiché si utilizza SQL Server 2008, è consigliabile inserire più righe alla volta; questa affermazione inserisce tre righe in una singola chiamata SQL

    INSERTO in valori di tabella (1,2,3), (4,5,6), (7,8,9)

ero terminando a circa 500 inserti distinti al secondo da un singolo thread. Dopo aver escluso la rete e la CPU (0 su client e server), supponevo che il disco io sul server fosse da incolpare, tuttavia l'inserimento in gruppi di tre mi ha permesso di ottenere 1500 inserti al secondo che escludono il disco io.

È chiaro che la libreria del client MS ha un limite superiore (e un'immersione nel reflector mostra un codice di completamento asincrono peloso).

Batching in questo modo, in attesa che vengano ricevuti gli eventi x prima di chiamare insert, ora inserisco a ~ 2700 inserti al secondo da un singolo thread che sembra essere il limite superiore per la mia configurazione.

Nota: se non si dispone di un flusso costante di eventi che arrivano a tutte le ore, si potrebbe prendere in considerazione l'aggiunta di un timer che vampate vostri inserti dopo un certo periodo (in modo che si vede l'ultimo evento della giornata!)

1

Alcuni suggerimenti per aumentare le prestazioni di inserimento:

  • aumento ADO.NET BatchSize
  • Scegli indice cluster della tabella di destinazione con saggezza, in modo che gli inserti non porterà ad divide nodo dell'indice cluster (ad esempio AutoInc colonna)
  • inserimento in una tabella heap temporanea prima, quindi emettere una grande "insert-by-selezionare" dichiarazione per spingere tutti i dati tabella di gestione temporanea nella tabella di destinazione effettiva
  • Applicare SqlBulkCopy
  • Scegliere "Bulk Logged" modello instad recupero "Full" modello di recupero
  • Posizionare un blocco di tabella prima di inserire (se lo scenario di business lo consente)

Tratto da Tips For Lightning-Fast Insert Performance On SqlServer