Abbiamo l'applicazione che scrive i registri nelle tabelle SQL di Azure. La struttura del tavolo è la seguente.Come ridurre l'utilizzo del log delle transazioni di SQL Server
CREATE TABLE [dbo].[xyz_event_history]
(
[event_history_id] [uniqueidentifier] NOT NULL,
[event_date_time] [datetime] NOT NULL,
[instance_id] [uniqueidentifier] NOT NULL,
[scheduled_task_id] [int] NOT NULL,
[scheduled_start_time] [datetime] NULL,
[actual_start_time] [datetime] NULL,
[actual_end_time] [datetime] NULL,
[status] [int] NOT NULL,
[log] [nvarchar](max) NULL,
CONSTRAINT [PK__crg_scheduler_event_history] PRIMARY KEY NONCLUSTERED
(
[event_history_id] ASC
)
)
tabella memorizzata come indice cluster da scheduled_task_id
colonna (non unico).
CREATE CLUSTERED INDEX [IDX__xyz_event_history__scheduled_task_id] ON [dbo].[xyz_event_history]
(
[scheduled_task_id] ASC
)
Il event_history_id
generato dall'applicazione, è casuale (non sequenziale) GUID. L'applicazione crea, aggiorna e rimuove le vecchie entità dalla tabella. La colonna log
di solito contiene 2-10 KB di dati, ma in alcuni casi può raggiungere i 5-10 MB. Gli articoli sono generalmente accessibili da PK (event_history_id
) e l'ordinamento più frequente è event_date_time desc
.
Il problema che vediamo dopo aver abbassato il livello delle prestazioni per SQL SQL su "S3" (100 DTU) sta superando i limiti di velocità del registro delle transazioni. Può essere visto chiaramente nella tabella sys.dm_exec_requests - ci saranno record con tipo di attesa LOG_RATE_GOVERNOR
(msdn).
Si verifica quando DB è in attesa della quota da scrivere nel registro.
Le operazioni che ho notato che causano grande impatto sul tasso di registro sono le eliminazioni da xyz_event_history
e gli aggiornamenti in log
colonna. Gli aggiornamenti fatti nel modo seguente.
UPDATE xyz_event_history
SET [log] = COALESCE([log], '') + @log_to_append
WHERE event_history_id = @id
Il modello di recupero per i database SQL Azure è FULL
e non può essere modificato.
Ecco le statistiche dell'indice fisico: ci sono molte pagine che hanno superato il limite di 8K per riga.
TableName AllocUnitTp PgCt AvgPgSpcUsed RcdCt MinRcdSz MaxRcdSz xyz_event_history IN_ROW_DATA 4145 47.6372868791698 43771 102 7864 xyz_event_history IN_ROW_DATA 59 18.1995058067705 4145 11 19 xyz_event_history IN_ROW_DATA 4 3.75277983691623 59 11 19 xyz_event_history IN_ROW_DATA 1 0.914257474672597 4 11 19 xyz_event_history LOB_DATA 168191 97.592290585619 169479 38 8068 xyz_event_history IN_ROW_DATA 7062 3.65090190264393 43771 38 46 xyz_event_history IN_ROW_DATA 99 22.0080800593032 7062 23 23 xyz_event_history IN_ROW_DATA 1 30.5534964170991 99 23 23 xyz_event_history IN_ROW_DATA 2339 9.15620212503089 43771 16 38 xyz_event_history IN_ROW_DATA 96 8.70488015814184 2339 27 27 xyz_event_history IN_ROW_DATA 1 34.3711391153941 96 27 27 xyz_event_history IN_ROW_DATA 1054 26.5034840622683 43771 28 50 xyz_event_history IN_ROW_DATA 139 3.81632073140598 1054 39 39 xyz_event_history IN_ROW_DATA 1 70.3854707190511 139 39 39
- Esiste un modo per ridurre l'utilizzo di log delle transazioni?
- In che modo il registro di SQL Server aggiorna le transazioni come nell'esempio sopra riportato? È solo un valore "vecchio" più "nuovo"? (Che sarebbe in teoria rendere l'aggiunta di piccoli pezzi di dati frequentemente del tutto inefficienti in termini di dimensioni del registro delle transazioni)
UPDATE (aprile, 20): Ho fatto alcuni esperimenti con suggerimenti in risposte e sono rimasto colpito dalla differenza rispetto a INSERT
anziché a UPDATE
.
di cui al successivo articolo di MSDN sulla struttura interna di registro delle transazioni di SQL Server (https://technet.microsoft.com/en-us/library/jj835093(v=sql.110).aspx):
i record di registrazione per registrare le modifiche dei dati o l'operazione logica eseguite o registrano la prima e dopo le immagini dei dati modificati . L'immagine precedente è una copia dei dati prima che l'operazione sia eseguita; l'immagine dopo è una copia dei dati dopo l'operazione è stata eseguita.
Questo rende automaticamente lo scenario con UPDATE ... SET X = X + 'more'
altamente inefficiente in termini di utilizzo log delle transazioni - che richiede la cattura "prima immagine".
Ho creato semplice suite di test per testare modo originale di aggiungere dati a "log" colonna contro il modo in cui abbiamo appena inseriamo nuovo pezzo di dati nella nuova tabella. I risultati che ho ottenuto sono abbastanza sorprendenti (per quanto mi riguarda, non troppo esperto con il ragazzo di SQL Server).
Il test è semplice: 5'000 volte aggiungono pezzi lunghi 1'024 caratteri di registro - solo 5 MB di testo come il risultato (non troppo male come si potrebbe pensare).
FULL recovery mode, SQL Server 2014, Windows 10, SSD
UPDATE INSERT Duration 07:48 (!) 00:02 Data file grow ~8MB ~8MB Tran. Log grow ~218MB (!) 0MB (why?!)
soli 5000 aggiornamenti che aggiungono 1 KB di dati può appendere fuori di SQL Server per 8 minuti (wow!) - non mi aspettavo che!
Penso domanda iniziale viene risolto a questo punto, ma i seguenti cresciuto:
-
Perché log delle transazioni crescere sembra lineare (non quadratica, come ci si può aspettare quando semplicemente catturare "prima" e "dopo" immagini)?Dal diagramma possiamo vedere che gli "articoli al secondo" crescono proporzionalmente alla radice quadrata - è come previsto se il sovraccarico cresce in modo lineare con la quantità di articoli inseriti. - Perché nel caso di inserimenti il log delle transazioni sembra avere le stesse dimensioni di prima di qualsiasi inserimento? Ho preso uno sguardo sul log delle transazioni (con Dell's Toad) per il caso con inserti e si presenta come solo la scorsa 297 oggetti sono in là - plausibilmente log delle transazioni ricevuti troncati, ma perché se è
FULL
modalità di recupero?
AGGIORNAMENTO (21 aprile). DBCC LOGINFO
uscita per custodia con INSERT
- prima e dopo. La dimensione fisica del file di registro corrisponde all'output - esattamente 1.048.576 byte su disco. Perché sembra che il registro delle transazioni rimanga ancora?
RecoveryUnitId FileId FileSize StartOffset FSeqNo Status Parity CreateLSN 0 2 253952 8192 131161 0 64 0 0 2 253952 262144 131162 2 64 0 0 2 253952 516096 131159 0 128 0 0 2 278528 770048 131160 0 128 0
RecoveryUnitId FileId FileSize StartOffset FSeqNo Status Parity CreateLSN 0 2 253952 8192 131221 0 128 0 0 2 253952 262144 131222 0 128 0 0 2 253952 516096 131223 2 128 0 0 2 278528 770048 131224 2 128 0
Per coloro che interessati Ho registrato attività "sqlserv.exe" utilizzando Process Monitor - vedo che il file venga sovrascritto ancora e ancora - sembra tratta di SQL Server voci di registro vecchie come non più necessari per qualche motivo: https://dl.dropboxusercontent.com/u/1323651/stackoverflow-sql-server-transaction-log.pml.
UPDATE (aprile 24). Sembra che finalmente ho iniziato a capire cosa sta succedendo e voglio condividere con voi. Il ragionamento di cui sopra è vero in generale, ma ha un avvertimento serio che ha anche prodotto confusione sullo strano riutilizzo del registro delle transazioni con INSERT
s.
Database si comporterà come in modalità di recupero SEMPLICE finché non venga presa primo backup completo (anche se è in modalità di recupero completo).
Siamo in grado di trattare i numeri e lo schema di cui sopra come vale per la modalità di recupero SIMPLE
, e devo rifare la mia misura per realeFULL
- sono ancora più sorprendente .
UPDATE INSERT Duration 13:20 (!) 00:02 Data file grow 8MB 11MB Tran. log grow 55.2GB (!) 14MB
è descritto tutto ciò che è consigliabile considerare http://dba.stackexchange.com/questions/29829/why-does-the-transaction-log-keep-growing-or-run-out-of-space –
@PiotrLasota, grazie per il suggerimento, ma poiché usiamo Azure SQL non ci occupiamo della gestione dei backup dei log e cose del genere. Il modello di recupero completo viene anche applicato da SQL di Azure. –
Evita gli aggiornamenti, il record tlog per un aggiornamento contiene i dati sia per annulla che per ripristina, ovvero i dati appena aggiornati e i dati prima dell'aggiornamento. Probabilmente inserirò solo gli inserti nella tua situazione. – dean