SQL Server: comment suivre la progression de la commande CREATE INDEX?

36

SQL Server 2014, Std Ed

J'ai lu que percent_complete dans dm_exec_requests ne fonctionne pas pour CREATE INDEX, et en pratique, percent_complete reste à 0. Donc ça n'aide pas.

J'utilise actuellement la méthode ci-dessous, qui au moins me montre le mouvement (que la création d'index n'est pas bloquée). Mais je n'ai aucune idée si je suis% 10 à travers le processus ou% 99.

J'ai essayé la méthode décrite ici: /dba//a/102545/6229 mais elle montre un temps d'achèvement est clairement erroné (il montre essentiellement `` maintenant '' pour un processus de plus de 60 minutes dans lequel je suis à 10 min )

Comment puis-je obtenir un indice?

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
Jonesome réintègre Monica
la source

Réponses:

56

Je pense que la requête suivante vous permettra au moins de vous rapprocher. Il utilise un DMV qui a été introduit dans SQL Server 2014: sys.dm_exec_query_profiles (et merci à Martin Smith de me l'avoir présenté via ce DBA.StackExchange Answer: Progression de l'instruction SELECT INTO :-).

Notez s'il vous plaît:

  • !! Vous devrez ajouter SET STATISTICS PROFILE ON;ou SET STATISTICS XML ON;dans le lot de requêtes qui fait le CREATE INDEX(et placé avant l' CREATE INDEXinstruction, si ce n'était pas évident), sinon aucune ligne n'apparaîtra dans ce DMV pour ce SPID / session_id !!

  • L' INopérateur est utilisé pour filtrer la Index Insertligne qui, si elle est incluse, augmentera les TotalRowsvaleurs, ce qui faussera les calculs puisque cette ligne n'affiche jamais aucune ligne traitée.

  • Le nombre de lignes affiché ici (c.-à-d. TotalRows) Est le double du nombre de lignes de la table en raison de l'opération prenant deux étapes, chacune opérant sur toutes les lignes: la première est une "analyse de table" ou "analyse d'index en cluster", et la seconde est le genre". Vous verrez «Table Scan» lors de la création d'un index clusterisé ou de la création d'un index non clusterisé sur un tas. Vous verrez "Analyse d'index clusterisé" lors de la création d'un index non clusterisé sur un index clusterisé.

  • Cette requête ne semble pas fonctionner lors de la création d'index filtrés. Pour une raison quelconque, les index filtrés a) n'ont pas l'étape "Tri" et b) le row_countchamp n'augmente jamais à partir de 0.
    Je ne sais pas ce que je testais auparavant, mais mes tests indiquent maintenant que les index filtrés sont capturés par cette requête. Doux. Mais attention, le nombre de lignes peut être désactivé (je verrai si je peux résoudre ce problème un jour).

  • Lors de la création d'un index cluster sur un tas qui contient déjà des index non cluster, les index non cluster doivent être reconstruits (pour échanger le RID - RowID - pour la ou les clés d'index cluster), et chaque reconstruction d'index non cluster sera être une opération distincte et donc non reflétée dans les statistiques renvoyées par cette requête lors de la création de l'index clusterisé.

  • Cette requête a été testée par rapport à:

    • Création:
      • Index non clusterisés sur un tas
      • un index clusterisé (aucun index non clusterisé n'existe)
      • Index non groupés sur l'index / la table groupés
      • un index cluster lorsque des index non cluster existent déjà
      • Index non clusterisés uniques sur l'index / la table clusterisés
    • Reconstruction (table avec index cluster et un index non cluster; testé sur SQL Server 2014, 2016, 2017 et 2019) via:
      • ALTER TABLE [schema_name].[table_name] REBUILD;( seul l'index clusterisé apparaît lors de l'utilisation de cette méthode )
      • 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;

Exemple de sortie:

                        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
Solomon Rutzky
la source
Si vous créez un index non cluster sur un segment de mémoire et que le nouvel index a la même clé qu'un index existant, la requête utilisera un opérateur avec la valeur physical_operator_nameset N'Index Scan', plutôt que N'Table Scan'ou N'Clustered Index Scan'. En outre, ce sera très lent, car il effectuera un tas de recherches RID.
Brian
Maintenant, si seulement cela fonctionnait sur ALTER INDEX ALL ON dbo.table REBUILD ..... <g>
Jonesome Reinstate Monica
1
BTW, cela fonctionne également bien pour surveiller la progression de la mise en œuvre de la compression des pages. sys.dm_exec_query_profiles est assez cool.
Todd Kleinhans du
2
@JonesomeReinstateMonica Je viens de mettre à jour légèrement la requête. Il semble qu'il capture effectivement les opérations de reconstruction, à la fois via ALTER INDEX ALLet même (partiellement) ALTER TABLE .. REBUILD. S'il-vous-plaît évaluez :-).
Solomon Rutzky
1
Salut @RoniVered Je viens de mettre à jour légèrement la requête dans la réponse afin qu'elle capture les reconstructions d'index non cluster. J'ai testé les deux types de commandes (mais pas DBCC, je viens d'y penser), et sur SQL Server 2019, 2017, 2016 et 2014. Il semble fonctionner de la même manière sur tous :-)
Solomon Rutzky