SQL Server: Bagaimana melacak kemajuan perintah CREATE INDEX?


36

SQL Server 2014, Std Ed

Saya telah membaca bahwa persen_lengkap di dm_exec_requests tidak berfungsi untuk CREATE INDEX, dan dalam praktiknya, persen_lengkap menempel pada 0. Jadi itu tidak membantu.

Saat ini saya menggunakan metode di bawah ini, yang setidaknya menunjukkan kepada saya gerakan (bahwa pembuatan indeks tidak diblokir). Tetapi saya tidak tahu apakah saya% 10 melalui proses atau% 99.

Saya mencoba metode yang dijelaskan di sini: /dba//a/102545/6229 tapi itu menunjukkan waktu penyelesaian yang jelas salah (itu pada dasarnya menunjukkan 'sekarang' untuk proses 60 menit lebih menit yang saya 10 menit ke dalam )

Bagaimana saya bisa mendapatkan petunjuk?

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

Jawaban:


56

Saya pikir pertanyaan berikut setidaknya akan membuat Anda cukup dekat. Itu menggunakan DMV yang diperkenalkan di SQL Server 2014: sys.dm_exec_query_profiles (dan terima kasih kepada Martin Smith karena memperkenalkannya kepada saya melalui DBA terkait ini. Jawaban StackExchange: Kemajuan SELECT INTO statement :-).

Tolong dicatat:

  • !! Anda akan perlu menambahkan SET STATISTICS PROFILE ON;atau SET STATISTICS XML ON;dalam batch query yang melakukan CREATE INDEX(dan ditempatkan sebelum itu CREATE INDEXpernyataan, jika itu tidak jelas), yang lain tidak ada baris akan muncul di DMV ini untuk itu SPID / session_id !!

  • The INOperator digunakan untuk menyaring para Index Insertbaris itu, jika disertakan, akan meningkatkan TotalRowsnilai-nilai, yang akan membelokkan perhitungan sejak baris yang tidak pernah menunjukkan setiap baris diproses.

  • Jumlah baris yang ditampilkan di sini (yaitu TotalRows) adalah dua kali lipat jumlah baris dari tabel karena operasi mengambil dua langkah, masing-masing beroperasi pada semua baris: pertama adalah "Table Scan" atau "Clustered Index Scan", dan yang kedua adalah "Sortir". Anda akan melihat "Pemindaian Tabel" saat membuat Indeks Berkelompok atau membuat Indeks Tidak Tertutup pada Heap. Anda akan melihat "Pemindaian Indeks Clustered" saat membuat Indeks NonClustered pada Indeks Clustered.

  • Kueri ini sepertinya tidak berfungsi saat membuat Indeks yang Difilter. Untuk beberapa alasan, Indeks yang Difilter a) tidak memiliki langkah "Urutkan", dan b) row_countbidang tidak pernah meningkat dari 0.
    Tidak yakin apa yang saya sedang menguji sebelumnya, tapi tes saya sekarang menunjukkan bahwa Disaring Indeks yang ditangkap oleh query ini. Manis. Meskipun hanya berhati-hatilah bahwa jumlah baris mungkin tidak aktif (saya akan melihat apakah saya dapat memperbaikinya suatu hari nanti).

  • Ketika membuat Indeks Clustered pada Heap yang sudah memiliki Indeks NonClustered di atasnya, Indeks NonClustered perlu dibangun kembali (untuk menukar RID - RowID - untuk Clustered Index Key (s)), dan setiap pembangunan kembali Indeks NonClustered akan menjadi operasi terpisah dan karenanya tidak tercermin dalam statistik yang dikembalikan oleh permintaan ini selama pembuatan Indeks Clustered.

  • Permintaan ini telah diuji terhadap:

    • Membuat:
      • Indeks NonClustered pada Heap
      • Indeks Clustered (tidak ada Indeks NonClustered ada)
      • Indeks NonClustered pada Indeks / Tabel Berkelompok
      • Indeks Clustered ketika Indeks NonClustered sudah ada
      • Indeks NonClustered Unik pada Indeks / Tabel Clustered
    • Membangun kembali (tabel dengan Clustered Index dan satu NonClustered Index; diuji pada SQL Server 2014, 2016, 2017, dan 2019) melalui:
      • ALTER TABLE [schema_name].[table_name] REBUILD;( hanya Indeks Clustered yang muncul saat menggunakan metode ini )
      • 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;

Output sampel:

                        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

Jika Anda membuat indeks non-cluster di heap dan indeks baru memiliki kunci yang sama dengan indeks yang ada, kueri akan menggunakan operator dengan physical_operator_nameset ke N'Index Scan', daripada N'Table Scan'atau N'Clustered Index Scan'. Juga, ini akan sangat lambat, karena akan melakukan banyak pencarian RID.
Brian

Sekarang jika hanya itu yang akan bekerja pada ALTER INDEX ALL ON dbo.table REBUILD ..... <g>
Jonesome Reinstate Monica

1
BTW, ini juga berfungsi dengan baik untuk memantau kemajuan penerapan kompresi halaman juga. sys.dm_exec_query_profiles sangat keren.
Todd Kleinhans

2
@JonesomeReinstateMonica Saya baru saja memperbarui kueri sedikit. Tampaknya memang menangkap operasi membangun kembali, baik melalui ALTER INDEX ALLdan bahkan (sebagian) ALTER TABLE .. REBUILD. Harap tinjau :-).
Solomon Rutzky

1
Hai @ Diatasi Saya baru saja memperbarui kueri dalam jawaban sedikit sehingga ia menangkap pembangunan kembali Indeks NonClustered. Saya menguji kedua jenis perintah (meskipun bukan DBCC, saya hanya memikirkan itu), dan pada SQL Server 2019, 2017, 2016, dan 2014. Tampaknya bekerja sama di semua dari mereka :-)
Solomon Rutzky
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.