In seguito a indagini con SQL Profiler un mio collega ha individuato la causa del peggioramento delle prestazioni dei bulk delete riguardanti un numero elevato di records.
Si tratta di un uso eccessivo di table variables (funzione CRM dbo.fn_CollectForCascadeDelete).
Le table variables sono messe in cache nel tempdb e vi rimangono fino al riavvio del servizio SQL Server (il tempdb è ricreato).
Una alternativa al riavvio consiste nello svuotamento della cache prima di effettuare la cancellazione: DBCC FREESYSTEMCACHE ('ALL')
Si tratta di un comando da usare con cautela perché causa una temporanea diminuzione delle prestazioni del server.
In un caso reale la cancellazione di 3600 records inizia con una velocità di 12 rec/s e finisce con 2 rec/s.
Lo svuotamento della cache consente di riportare la velocità al livello iniziale, ma le prestazioni degradano nuovamente.
Una soluzione potrebbe essere lo svuotamento periodico della cache solo in presenza della table variable usata dal bulk delete:
select t.[object_id] from tempdb.sys.tables t with(nolock) inner join ( select [object_id] from tempdb.sys.columns with(nolock) where [name] in ('o','t'/*,'r'*/,'p') group by [object_id] having count([object_id]) = 3 ) c on c.[object_id] = t.[object_id] where datediff(mi, t.create_date, getdate()) > 20 if @@rowcount > 0 DBCC FREESYSTEMCACHE ('ALL')
In questo script cerco nel tempdb le table variables CRM create da almeno 20min.
Un'altra causa di lentezza in fase di cancellazione è la mancanza di diversi indici sulle foreign keys delle tabelle CRM. Un esempio è il campo AsyncOperationId della tabella WorkFlowLogBase.
CREATE NONCLUSTERED INDEX [IX_lk_workflowlog_asyncoperation] ON [dbo].[WorkflowLogBase] ([AsyncOperationId])
Ache questo articolo di microsoft parla del problema.
http://support.microsoft.com/kb/968520/eng
|