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.