2012-04-25 2 views
5

Eventuali duplicati:
Multiple INSERT statements vs. single INSERT with multiple VALUESperché è l'inserimento di una singola riga x volte più veloce di inserimento x righe alla volta

sto facendo un po 'di analisi delle prestazioni sulle transazioni per l'elaborazione batch per un post sul blog e ho notato che quando si utilizza un'istruzione di inserimento batch, si comporta molto più lentamente delle singole istruzioni SQL equivalenti.

inserimento di 1000 righe, come di seguito dura circa 3s

INSERT TestEntities (TestDate, TestInt, TestString) VALUES 
('2011-1-1', 11, 'dsxcvzdfdfdfsa'), 
('2011-1-1', 11, 'dsxcvzdfdfdfsa'), 
('2011-1-1', 11, 'dsxcvzdfdfdfsa') 

inserimento di 1000 righe, come di seguito prende 130ms

INSERT TestEntities (TestDate, TestInt, TestString) VALUES ('2011-1-1', 11, 'dsxcvzdfdfdfsa') 
INSERT TestEntities (TestDate, TestInt, TestString) VALUES ('2011-1-1', 11, 'dsxcvzdfdfdfsa') 
INSERT TestEntities (TestDate, TestInt, TestString) VALUES ('2011-1-1', 11, 'dsxcvzdfdfdfsa') 

Questo sembra accadere solo la prima volta che si utilizza un inserto in batch sul tavolo ma è riproducibile.

Si noti inoltre i dati im inserimento è casuale (ma lo stesso per entrambe le query)

EDIT:

heres il mio caso Repro con il manichino im dati casuali utilizzando per questo caso: https://gist.github.com/2489133

+1

@MikaelEriksson sì questo è lo stesso problema malato vicino questo –

+0

@blam dare un'occhiata a http: // StackOverflow.com/q/8635818/1070291 spiega il problema in modo molto più approfondito, ha anche piani di query –

risposta

3

Il problema qui secondo Multiple INSERT statements vs. single INSERT with multiple VALUES è che quando SQL ottiene l'interrogazione deve calcolare un piano di query sulla prima esecuzione. Per un singolo inserto questo è bello e veloce, in quanto non c'è molto da calcolare, e dopo aver costruito il piano di query lo ri-utilizza solo 1000 volte.

nello scenario batch ci sono variabili 3k che devono essere incorporate nel piano di query che richiede molto più tempo per il calcolo.

Una caratteristica pazzesca che @MartinSmith sottolinea è che esiste un numero prestazionale magico intorno a una dimensione di batch fino a 250 righe, il che significa che il calcolo del piano è molto basso.

spezzando il sopra query in 5 200 dichiarazioni di fila riduce il tempo di esecuzione per 94ms per 1000 righe

0

Il primo è una singola istruzione che viene eseguita come una singola transazione. Il secondo è 1000 istruzioni con il sovraccarico di 1000 transazioni. La differenza dovrebbe ridursi quando si racchiude il secondo in begin transaction e commit transaction.

+0

Entrambi questi sono in esecuzione all'interno di transazioni, ma la cosa strana è che il secondo è il più veloce per un fattore di 20. Mi aspetto il primo ad essere più veloce, il suo payload più piccolo e una singola affermazione come dici tu –

+0

Nota che sta sostenendo che la singola istruzione all-in-one esegue SLOWER. –

+1

@HotLicks: quello con 'values' ha solo 1 transazione, che mi aspetterei di essere più veloce. Se entrambi sono già in una transazione, come i commenti di Luca, questa risposta non fornisce alcuna spiegazione. – Andomar

1

Il primo elemento è un'istruzione di grandi dimensioni che deve essere analizzata, quindi il tempo extra trascorso in questo campo è rappresentato dall'overhead di un lavoro di analisi di grandi dimensioni anziché di 1000 piccoli.

Sebbene non abbia eseguito il test per tutte le 1000 righe, ho eseguito il test per 3 e ho rilevato che il piano di esecuzione per la singola istruzione di inserimento è maggiore. Si noti inoltre che per 3 inserti separati, viene riutilizzato solo un piccolo piano.

enter image description here

enter image description here