Inserisci aumenti delle prestazioni sotto carico: perché?


19

Ho un pezzo di codice che esegue inserimenti in tabelle altamente denormalizzate. Le tabelle hanno numeri di colonne che vanno da ~ 100 a 300+. Questo è SQL Server 2008 R2, in esecuzione su Windows Server 2008.

Ogni inserimento consiste nell'inserimento in un numero di tabelle nella stessa transazione. Alcuni inserti sono raggruppati da NHibernate, ma alcuni non possono esserlo, ma sono comunque tutti nella stessa transazione.

Quando eseguo inserimenti per esempio 500 volte chiamando ripetutamente un pezzo di codice che esegue l'inserimento, ottengo una media di ~ 360 ms.

La cosa strana è che, quando eseguo il codice di test contemporaneamente usando 4 processi (lo stesso exe viene eseguito da 4 diversi prompt dei comandi in Windows Server 2008), le prestazioni di inserimento per chiamata migliorano molto. Vedo scoppi che vanno fino a 90 ms (quasi X4 più veloce). Sto misurando il tempo di inserimento dal codice.

Poiché i 4 processi non si conoscono a vicenda, presumo che ciò abbia a che fare con SQL Server, ma non ho assolutamente idea del perché. Vorrei sapere perché questo sta accadendo e se esiste una configurazione che mi consenta di ottenere le stesse prestazioni quando gli inserti non sono così frequenti.

Suggerimenti sui metodi di monitoraggio di SQL Server per comprendere cosa sta succedendo a livello di db sono ugualmente benvenuti.

Risposte:


15

Una possibile ragione è che quattro processi simultanei generano un modello più favorevole di flush dei log, il che significa in genere che ogni flush dei log scrive più dati di quanto non avvenga con un singolo processo di esecuzione.

Per determinare se il throughput del registro delle transazioni / la dimensione del flush è un fattore, monitorare:

Cerca i limiti interni da raggiungere. In SQL Server 2008 R2 possono esserci al massimo 32 I / O di scaricamento dei log (asincroni) in sospeso per database su versioni a 64 bit (solo 8 su 32 bit). Esiste anche un limite di dimensione totale per gli IO in sospeso di 3840 KB.

Ulteriori informazioni e ulteriori letture:


12

Tutto su @PaulWhite dice, più ...

Se sono presenti chiavi esterne, ogni inserimento richiederà un controllo da eseguire su ciascuna tabella a cui viene fatto riferimento. Mi sembra come te, dato che stai ricevendo solo 360ms, il che mi sembra lento.

Ad ogni modo, controllare quelle tabelle è enormemente aiutato avendo già quei dati nella RAM, piuttosto che doverli caricare sul disco.

Mi sembra che caricare i dati nella RAM sia una parte significativa della tua esecuzione e che debba avvenire solo una volta.

Potrebbe anche essere un'efficace memorizzazione nella cache del piano e che le tue query devono essere compilate la prima volta, con le chiamate successive in grado di evitare quella fase.


Grazie Rob. Il mio problema di prestazioni è associato all'alto numero di tabelle utilizzate durante un inserimento. Non ci sono chiavi esterne, le ho rimosse per motivi di prestazioni e i miei requisiti di modello e dominio mi consentono di farlo. Non sto caricando i dati nella RAM e i miei inserti sono modellati dinamicamente dalle richieste in arrivo, che cambiano continuamente. Fondamentalmente sto abusando di uno schema a stella / fiocco di neve (ish) per OLTP e sto cercando di ottenere le migliori prestazioni che posso.
Mahonya,

2
@mahonya, anche se non stai caricando esplicitamente i dati nella RAM, SQL Server deve prima leggere l'indice e le pagine di dati necessari nella cache del buffer prima di eseguire l'operazione di inserimento. I thread di inserimento simultanei possono avere l'effetto di riscaldare la cache in modo tale che un thread incorre nell'overhead di lettura e l'altro acceda ai dati nella cache.
Dan Guzman,

Grazie @DanGuzman - e sì, Mahonya, c'è una forte possibilità che la tua cache sia ben riscaldata. Verificherei le tue attese per vedere se l'I / O fisico sta causando il tuo collo di bottiglia.
Rob Farley,

Grazie @DanGuzman D'accordo, l'accelerazione della cache dell'indice db è qualcosa che sono abituato a vedere in Postgres probabilmente ho frainteso l'input di Rob.
Mahonya,

-3

alcuni server / cpus / os ricordano gli schemi. come cache.

Dato che stai facendo la stessa cosa 4 volte, sono sicuro che ci sono modi in cui può tagliare gli angoli, quello che immagino è che il primo modo in cui lo fai, lo considera come un lungo processo (esempio1) ma nel secondo modo vede il codice riutilizzato e lo esegue come cache (esempio2) oppure potrebbe essere il primo processo troppo grande per adattarlo a tutto (ram esempio3).

esempio1: 0111110000110111110000111011111000011110111110000

esempio2: 0111110000 | 11 | 0111110000 | 111 | 0111110000 | 1111 | 0111110000

esempio3: 0111110000011111000001111100000111110000 esempio3: loop: 0111110000

So che il server Ubuntu lo fa con ripetute query mysql. Posso salvarli nella cache, anche se in realtà l'unica differenza di tempo è 10-40mms ma si somma. Quando ero a scuola c'erano delle lezioni che mostravano che devi fare in modo che i programmi (perl / php) utilizzino quella cache per essere più veloci.

Ma potrebbe dipendere dal programma, dalla lingua, dalla compilazione o da come è stato programmato.

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.