SQL Server: come tenere traccia dell'avanzamento del comando CREATE INDEX?


36

SQL Server 2014, Ed. Standard

Ho letto che percent_complete in dm_exec_requests non funziona per CREATE INDEX e, in pratica, percent_complete si attacca a 0. Quindi non aiuta.

Attualmente uso il metodo seguente, che mi mostra almeno il movimento (che la creazione dell'indice non è bloccata). Ma non ho idea se sono% 10 attraverso il processo o% 99.

Ho provato il metodo descritto qui: /dba//a/102545/6229 ma mostra un tempo di completamento est chiaramente errato (mostra sostanzialmente "adesso" per un processo di oltre 60 minuti entro 10 minuti )

Come posso avere un indizio?

SELECT percent_complete, estimated_completion_time, reads, writes, logical_reads, text_size, *
FROM
sys.dm_exec_requests AS r
WHERE
r.session_id <> @@SPID
AND r.session_id = 58

Risposte:


56

Penso che la seguente domanda almeno ti avvicinerà abbastanza. Si avvale di un DMV che è stato introdotto in SQL Server 2014: sys.dm_exec_query_profiles (e grazie a Martin Smith per avermelo presentato tramite questa risposta DBA.StackExchange correlata: Progresso dell'istruzione SELECT INTO :-).

Notare che:

  • !! Sarà necessario aggiungere SET STATISTICS PROFILE ON;o SET STATISTICS XML ON;nel batch query che sta facendo il CREATE INDEX(e posto davanti la CREATE INDEXdichiarazione, se non fosse ovvio), altrimenti nessuna riga verranno visualizzati in questo DMV per questo SPID / session_id !!

  • L' INoperatore viene utilizzato per filtrare la Index Insertriga che, se inclusa, aumenterà i TotalRowsvalori, il che distorcerà i calcoli poiché quella riga non mostra mai alcuna riga elaborata.

  • Il conteggio delle righe visualizzato qui (ovvero TotalRows) è il doppio del conteggio delle righe della tabella a causa dell'operazione che esegue due passaggi, ognuno dei quali opera su tutte le righe: la prima è una "Scansione tabella" o "Scansione indice cluster", e la seconda è il tipo". Vedrai "Scansione tabella" durante la creazione di un indice cluster o la creazione di un indice non cluster su un heap. Vedrai "Scansione indice cluster" durante la creazione di un indice non cluster su un indice cluster.

  • Questa query non sembra funzionare durante la creazione di indici filtrati. Per qualche motivo, gli indici filtrati a) non hanno il passaggio "Ordina" e b) il row_countcampo non aumenta mai da 0.
    Non sono sicuro di ciò che stavo testando prima, ma i miei test ora indicano che gli indici filtrati vengono acquisiti da questa query. Dolce. Ma fai attenzione che il conteggio delle righe potrebbe essere spento (vedrò se un giorno riuscirò a risolverlo).

  • Quando si crea un indice cluster su un heap su cui sono già presenti indici non cluster, è necessario ricostruire gli indici non cluster (per scambiare il RID - RowID - per le chiavi dell'indice cluster) e ogni ricostruzione dell'indice non cluster essere un'operazione separata e quindi non riflessa nelle statistiche restituite da questa query durante la creazione dell'Indice cluster.

  • Questa query è stata testata con:

    • Creazione:
      • Indici non cluster su un heap
      • un indice cluster (non esistono indici non cluster)
      • Indici non cluster nell'indice / tabella cluster
      • un indice cluster quando già esistono indici non cluster
      • Indici non cluster univoci sull'indice / tabella cluster
    • Ricostruzione (tabella con indice cluster e un indice non cluster; testato su SQL Server 2014, 2016, 2017 e 2019) tramite:
      • ALTER TABLE [schema_name].[table_name] REBUILD;( solo l'indice cluster viene visualizzato quando si utilizza questo metodo )
      • ALTER INDEX ALL ON [schema_name].[table_name] REBUILD;
      • ALTER INDEX [index_name] ON [schema_name].[table_name] REBUILD;
DECLARE @SPID INT = 51;

;WITH agg AS
(
     SELECT SUM(qp.[row_count]) AS [RowsProcessed],
            SUM(qp.[estimate_row_count]) AS [TotalRows],
            MAX(qp.last_active_time) - MIN(qp.first_active_time) AS [ElapsedMS],
            MAX(IIF(qp.[close_time] = 0 AND qp.[first_row_time] > 0,
                    [physical_operator_name],
                    N'<Transition>')) AS [CurrentStep]
     FROM sys.dm_exec_query_profiles qp
     WHERE qp.[physical_operator_name] IN (N'Table Scan', N'Clustered Index Scan',
                                           N'Index Scan',  N'Sort')
     AND   qp.[session_id] = @SPID
), comp AS
(
     SELECT *,
            ([TotalRows] - [RowsProcessed]) AS [RowsLeft],
            ([ElapsedMS] / 1000.0) AS [ElapsedSeconds]
     FROM   agg
)
SELECT [CurrentStep],
       [TotalRows],
       [RowsProcessed],
       [RowsLeft],
       CONVERT(DECIMAL(5, 2),
               (([RowsProcessed] * 1.0) / [TotalRows]) * 100) AS [PercentComplete],
       [ElapsedSeconds],
       (([ElapsedSeconds] / [RowsProcessed]) * [RowsLeft]) AS [EstimatedSecondsLeft],
       DATEADD(SECOND,
               (([ElapsedSeconds] / [RowsProcessed]) * [RowsLeft]),
               GETDATE()) AS [EstimatedCompletionTime]
FROM   comp;

Uscita campione:

                        Rows                 Percent   Elapsed  Estimated    Estimated
CurrentStep  TotalRows  Processed  RowsLeft  Complete  Seconds  SecondsLeft  CompletionTime
-----------  ---------  ---------  --------  --------  -------  -----------  --------------
Clustered    11248640   4786937    6461703   42.56     4.89400  6.606223     2016-05-23
Index Scan                                                                   14:32:40.547

Se si crea un indice non cluster su un mucchio e il nuovo indice ha lo stesso tasto di un indice esistente, la query si avvarrà di un operatore con physical_operator_nameset a N'Index Scan', piuttosto che N'Table Scan'o N'Clustered Index Scan'. Inoltre, sarà molto lento, poiché eseguirà un sacco di ricerche RID.
Brian,

Ora, se solo funzionasse su ALTER INDEX TUTTO SU dbo.table REBUILD ..... <g>
Jonesome Reinstate Monica

1
A proposito, funziona bene anche per monitorare i progressi nell'implementazione della compressione delle pagine. sys.dm_exec_query_profiles è piuttosto interessante.
Todd Kleinhans,

2
@JonesomeReinstateMonica Ho appena aggiornato leggermente la query. Sembra che effettivamente catturi le operazioni di ricostruzione, sia via ALTER INDEX ALLche anche (parzialmente) ALTER TABLE .. REBUILD. Per favore, revisiona :-).
Solomon Rutzky,

1
Ciao @RoniVered Ho appena aggiornato leggermente la query nella risposta in modo che acquisisca le ricostruzioni dell'indice non cluster. Ho testato entrambi i tipi di comandi (anche se non DBCC, ci avevo appena pensato) e su SQL Server 2019, 2017, 2016 e 2014. Sembra funzionare allo stesso modo su tutti loro :-)
Solomon Rutzky il
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.