SQL Server: как отслеживать ход выполнения команды CREATE INDEX?


36

SQL Server 2014, стандартный выпуск

Я читал, что процент_компонента в dm_exec_requests не работает для CREATE INDEX, и на практике, процент_компонента остается на 0. Так что это не помогает.

В настоящее время я использую метод ниже, который по крайней мере показывает мне движение (что создание индекса не заблокировано). Но я понятия не имею, нахожусь ли я% 10 в процессе или% 99.

Я попробовал метод, описанный здесь: /dba//a/102545/6229, но он показывает явно неправильное время завершения EST (он в основном показывает «сейчас» для 60 + минутного процесса, который я 10 минут в )

Как я могу получить подсказку?

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

Ответы:


56

Я думаю, что следующий запрос по крайней мере приблизит вас. Он использует DMV, который был представлен в SQL Server 2014: sys.dm_exec_query_profiles (и спасибо Мартину Смиту за представление его мне через этот связанный DBA.StackExchange Ответ: Ход выполнения инструкции SELECT INTO :-).

Пожалуйста, обратите внимание:

  • !! Вам нужно будет добавить SET STATISTICS PROFILE ON;или SET STATISTICS XML ON;в пакете запроса , который делает CREATE INDEX(и помещен перед тем в CREATE INDEXзаявлении, если это не было очевидно), еще ни одна строка не будет отображаться в этом DMV для этого ИСП / session_id !!

  • INОператор используется , чтобы отфильтровать Index Insertстроки , что, если он включен, приведет к увеличению TotalRowsзначения, которые будут искажать расчеты , так как эта строка никогда не показывает каких - либо обработанных строк.

  • Отображаемое здесь количество строк (то есть TotalRows) является двойным числом строк таблицы из-за операции, выполняемой в два этапа, каждый из которых работает со всеми строками: первый - «Сканирование таблицы» или «Сканирование кластерного индекса», а второй - «Сортировка». Вы увидите «Сканирование таблицы» при создании кластеризованного индекса или некластеризованного индекса в куче. Вы увидите «Сканирование кластеризованного индекса» при создании некластерного индекса в кластерном индексе.

  • Этот запрос не работает при создании отфильтрованных индексов. По какой-то причине отфильтрованные индексы а) не имеют шага «Сортировка», и б) row_countполе никогда не увеличивается с 0.
    Не уверен , что я испытывал раньше, но мои тесты теперь указывают , что отфильтрованных индексов будут захвачены этим запросом. Милая. Хотя остерегайтесь того, что число строк может быть выключено (я посмотрю, смогу ли я когда-нибудь это исправить).

  • При создании кластерного индекса в куче, в которой уже есть некластеризованные индексы, необходимо перестроить некластеризованные индексы (чтобы поменять RID - RowID - для ключа (ключей) кластерного индекса), и каждая перестройка некластерного индекса будет быть отдельной операцией и, следовательно, не отражаться в статистике, возвращаемой этим запросом при создании кластерного индекса.

  • Этот запрос был проверен на:

    • Создание:
      • Некластеризованные индексы в куче
      • кластеризованный индекс (некластеризованных индексов не существует)
      • Некластерные индексы в кластерном индексе / таблице
      • кластерный индекс, когда некластерные индексы уже существуют
      • Уникальные некластеризованные индексы в кластерном индексе / таблице
    • Перестройка (таблица с кластеризованным индексом и одним некластеризованным индексом; протестирована на SQL Server 2014, 2016, 2017 и 2019) с помощью:
      • ALTER TABLE [schema_name].[table_name] REBUILD;( при использовании этого метода отображается только кластерный индекс )
      • 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;

Образец вывода:

                        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

Если вы создаете некластеризованный индекс в куче, а новый индекс имеет тот же ключ, что и существующий индекс, запрос будет использовать оператор с physical_operator_nameустановленным на N'Index Scan', а не N'Table Scan'или N'Clustered Index Scan'. Кроме того, он будет очень медленным, так как он выполнит несколько поисков RID.
— Брайан

Теперь, если бы только это работало над ALTER INDEX ALL ON dbo.table REBUILD ..... <g>
— Jonesome Reinstate Monica

1
Кстати, это также хорошо работает для отслеживания прогресса в реализации сжатия страниц. sys.dm_exec_query_profiles - это круто.
— Тодд Кляйнханс

2
@JonesomeReinstateMonica Я только немного обновил запрос. Кажется, что он действительно захватывает операции восстановления, как через, так ALTER INDEX ALLи даже (частично) ALTER TABLE .. REBUILD. Пожалуйста ознакомтесь :-).
— Соломон Руцкий

1
Привет @ RoniVered Я просто немного обновил запрос в ответе, чтобы он перехватывал пересчеты NonClustered Index. Я протестировал оба типа команд (хотя не DBCC, я только что подумал об этом) и на SQL Server 2019, 2017, 2016 и 2014. Кажется, что они работают одинаково для всех из них :-)
— Соломон Руцки
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.