SQL Server: Як відстежувати хід команди CREATE INDEX?


36

SQL Server 2014, Std Ed

Я читав, що відсоток_комплекту в dm_exec_requests не працює для CREATE INDEX, а на практиці проценти_комплектів дотримуються значення 0. Так що це не допомагає.

Зараз я використовую метод нижче, який принаймні показує мені рух (що створення індексу не заблоковано). Але я не маю ідеї, якщо я% 10 через процес або% 99.

Я спробував описаний тут метод: /dba//a/102545/6229, але він показує явно неправильний час завершення (він в основному показує "зараз" протягом 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), є подвоєним числом рядків таблиці через операцію, яка робить два кроки, кожен з яких працює на всіх рядках: перший - "Сканування таблиці" або "Кластерне сканування індексів", а другий - "Сортування". Ви побачите "Сканування таблиці" під час створення індексу кластеру або створення некластеризованого індексу на купі. Ви побачите "Сканування кластерного індексу" під час створення некластеризованого індексу на кластерному індексі.

  • Схоже, цей запит не працює при створенні відфільтрованих індексів. Чомусь відфільтровані індекси a) не мають кроку "Сортування", і б) 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 НА dbo.table ВИПУСК ..... <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.