Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Mengotomatiskan Defragmentasi Indeks di Database MS SQL Server

Pengantar

World Wide Web menawarkan banyak informasi tentang defragmentasi indeks SQL Server atau pembangunan kembali indeks SQL Server. Namun, sebagian besar rekomendasi merujuk ke database yang memiliki waktu muat minimum (kebanyakan, pada malam hari).

Dan bagaimana dengan database yang digunakan untuk keduanya, modifikasi data, dan pengambilan informasi 24/7?

Pada artikel ini, saya akan memberikan mekanisme untuk mengotomatisasi defragmentasi indeks SQL Server yang diterapkan dalam database yang digunakan di perusahaan tempat saya bekerja. Mekanisme ini memungkinkan defragmentasi indeks yang diperlukan secara teratur karena fragmentasi indeks berlangsung terus-menerus dalam sistem 24/7. Seringkali, ini tidak cukup untuk melakukan defragmentasi indeks sekali sehari.

Solusi

Pertama, mari kita lihat pendekatan umum:

  1. Membuat tampilan yang menunjukkan indeks mana yang telah terfragmentasi dan persentase indeks yang terfragmentasi.
  2. Membuat tabel untuk menyimpan hasil defragmentasi indeks.
  3. Membuat prosedur tersimpan untuk menganalisis dan mendefrag indeks yang dipilih.
  4. Membuat tampilan untuk melihat statistik hasil defragmentasi indeks.
  5. Membuat tugas di Agen untuk menjalankan prosedur tersimpan yang diterapkan.

Dan sekarang, mari kita lihat implementasinya:

1. Membuat tampilan yang menunjukkan indeks mana yang telah terfragmentasi dan persentase indeks yang terfragmentasi:

GUNAKAN [Database_Name]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE view [srv].[vIndexDefrag]dengan info sebagai (SELECT [object_id], database_id, index_id, index_type_desc, index_level, fragment_count, avg_count_fragmentasi_fragmentasi_in, jumlah_penghitungan_fragmentasi_in, avg_fragmentasi_fragmentasi_in jumlah_fragmentasi. .dm_db_index_physical_stats (DB_ID(N'Database_Name') , NULL, NULL, NULL , N'DETAILED') dimana index_level =0 )PILIH b.name sebagai db, s.name sebagai shema, t.name sebagai tb, i.index_id sebagai idx, i.database_id, idx.name sebagai index_name, i.index_type_desc, i.index_level sebagai [level], i.[object_id], i.fragment_count sebagai frag_num, round(i.avg_fragmentation_in_percent,2) sebagai frag, round(i .avg_fragment_size_in_pages,2) sebagai frag_page, i.page_count sebagai [page], i.record_count sebagai rec, i.ghost_record_count sebagai ghost, bulat(i.avg_fragmentation_in_percent*i.page_count,0) sebagai funcFROM Info saat saya bergabung dengan [sys]. [database] sebagai b pada i.database_id =b.database_idinner bergabung dengan [sys].[all_objects] sebagai t pada i.object_id =t.object_idinner gabungkan [sys].[schemas] sebagai s pada t.[schema_id] =s.[schema_id]inner gabung [sys].[indexes] sebagai idx pada t.object_id =idx.object_id dan idx.index_id =i.index_id di mana i.avg_fragmentation_in_percent>=30 dan i.index_type_desc <> 'HEAP';GO

Tampilan ini hanya menampilkan indeks dengan persentase fragmentasi lebih besar dari 30, yaitu indeks yang memerlukan defragmentasi. Ini hanya menunjukkan indeks yang bukan tumpukan, karena yang terakhir dapat menyebabkan efek negatif, seperti pemblokiran tumpukan tersebut, atau fragmentasi indeks lebih lanjut.

Tampilan menggunakan tampilan sistem yang penting sys.dm_db_index_physical_stats.

2. Membuat tabel untuk menyimpan hasil defrag indeks:

GUNAKAN [Database_Name]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Defrag]( [ID] [bigint] IDENTITY(794,1) NOT NULL, [db] [nvarchar](100) NULL, [shema] [nvarchar](100) NULL, [tabel] [nvarchar](100) NULL, [IndexName] [nvarchar](100) NULL, [frag_num] [int] NULL, [frag] [desimal](6, 2) NULL , [halaman] [int] NULL, [rec] [int] NULL, [func] [int] NULL, [ts] [datetime] NULL, [tf] [datetime] NULL, [frag_after] [desimal](6, 2) NULL, [object_id] [int] NULL, [idx] [int] NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Defrag] PRIMARY KEY CLUSTERED ( [ID] ASC)DENGAN (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[Defrag] ADD CONSTRAINT [DF_Defrag_InsertUTCDate [getutcdate] DEFAULT 

Hal terpenting tentang tabel ini adalah mengingat penghapusan data (misalnya, data yang lebih lama dari 1 bulan).

Bidang tabel akan dapat dipahami dari poin berikutnya.

3. Membuat prosedur tersimpan untuk menganalisis dan mendefrag indeks yang dipilih:

GUNAKAN [Database_Name]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[AutoDefragIndex]ASBEGIN SET NOCOUNT ON; --mendeklarasikan variabel yang diperlukan mendeklarasikan @IndexName nvarchar(100) --index name ,@db nvarchar(100) --database name ,@Shema nvarchar(100) --schema name ,@Table nvarchar(100) --table name , @SQL_Str nvarchar (2000) --string untuk pembuatan perintah ,@frag desimal(6,2) --persentase fragmentasi sebelum defragmentasi ,@frag_after desimal(6,2) --persentase fragmentasi setelah defragmentasi --Jumlah fragmen di akhir tingkat unit alokasi IN_ROW_DATA ,@frag_num int ,@func int --round(i.avg_fragmentation_in_percent*i.page_count,0) ,@page int --jumlah halaman indeks ,@rec int --total jumlah catatan ,@ ts datetime --tanggal dan waktu defragmentasi mulai ,@tf datetime --tanggal dan waktu defragmentasi selesai --Tabel atau lihat ID objek yang indeksnya dibuat ,@object_id int ,@idx int; --index ID --mendapatkan tanggal dan waktu saat ini ditetapkan @ts =getdate(); --Mendapatkan indeks berikutnya untuk defragmentasi --Di sini indeks penting dipilih. Pada saat itu, situasi ketika satu indeks didefrag secara teratur, sementara indeks lain tidak dipilih untuk defragmentasi tidak mungkin terjadi. pilih top 1 @IndexName =index_name, @db=db, @Shema =shema, @Table =tb, @frag =frag, @frag_num =frag_num, @func=func, @page =[page], @rec =rec, @object_id =[object_id], @idx =idx from [srv].[vIndexDefrag] diurutkan berdasarkan func*power((1.0- convert(float,(select count(*) from SRV.[srv].[Defrag] vid where vid.db=db dan vid.shema =shema dan vid.[table] =tb dan vid.IndexName =index_name)) / convert(float, case when (ada (pilih top 1 1 dari SRV.[srv].[Defrag ] vid1 where vid1.db=db)) then (pilih count(*) from SRV.[srv].[Defrag] vid1 where vid1.db=db) else 1.0 end)) ,3) desc --if kita mendapatkan seperti itu index if(@db is not null) begin --index reorganisasi set @SQL_Str ='ubah indeks ['[email protected]+'] pada ['[email protected]+'].['[email protected]+'] Mengatur'; jalankan sp_executesql @SQL_Str; --mendapatkan tanggal dan waktu saat ini ditetapkan @tf =getdate() --mendapatkan persentase fragmentasi setelah defragmentasi SELECT @frag_after =avg_fragmentation_in_percent FROM sys.dm_db_index_physical_stats (DB_ID(@db), @object_id, @idx, NULL , N'DETAILED') di mana index_level =0; --menulis hasil kerja insert ke dalam SRV.srv.Defrag( [db], [shema], [table], [IndexName], [frag_num], [frag], [page], [rec], ts, tf , frag_after, object_id, idx ) pilih @db, @shema, @table, @IndexName, @frag_num, @frag, @page, @rec, @ts, @tf, @frag_after, @object_id, @idx; --memperbarui statistik untuk kumpulan indeks @SQL_Str ='PERBARUI STATISTIK ['[email protected]+'].['[email protected]+'] ['[email protected]+']'; jalankan sp_executesql @SQL_Str; akhirEND

4. Membuat tampilan untuk melihat statistik hasil defragmentasi indeks:

GUNAKAN [Database_Name]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE view [srv].[vStatisticDefrag] asSELECT top 1000 [db] ,[shema] ,[table] ,[IndexName] ,avg([frag]) sebagai AvgFrag ,avg ,avg [frag_after]) sebagai AvgFragAfter ,avg(page) sebagai AvgPage FROM [srv].[Defrag] grup menurut [db], [shema], [table], [IndexName] diurutkan berdasarkan abs(avg([frag])-avg ([frag_after])) desc;GO

Tampilan ini dapat digunakan untuk memberi tahu administrator setiap hari tentang hasil otomatisasi defragmentasi indeks.

5. Membuat tugas di Agen untuk menjalankan prosedur tersimpan yang diterapkan

Di sini, kita perlu memilih waktu dengan cara eksperimental. Dalam kasus saya, di suatu tempat saya mendapat 5 menit, di suatu tempat – 1 jam.

Algoritme ini dapat diperluas pada beberapa database, tetapi dalam kasus ini, kami memerlukan poin tambahan 6:

Mengumpulkan semua statistik otomatisasi defragmentasi indeks di satu tempat untuk selanjutnya dikirim ke administrator.

Dan sekarang, saya ingin membahas rekomendasi yang sudah disediakan untuk dukungan indeks:

  1. Defragmentasi semua indeks secara bersamaan selama pemuatan basis data minimal tidak dapat diterima untuk sistem 24/7, karena indeks terus-menerus terfragmentasi dan hampir tidak ada waktu ketika basis data tidak digunakan.
  2. Reorganisasi indeks SQL Server – operasi ini memblokir tabel atau partisi (dalam kasus indeks yang dipartisi), yang tidak baik untuk sistem 24/7. Kemudian, pembuatan ulang indeks dalam mode waktu nyata hanya didukung dalam solusi Perusahaan, dan juga dapat menyebabkan kerusakan data.

Metode ini tidak optimal, tetapi dapat berhasil mengatasi dengan memastikan bahwa indeks didefrag dengan benar (tidak melebihi 30-40% dari fragmentasi) untuk penggunaan selanjutnya oleh pengoptimal untuk membangun rencana eksekusi.

Saya akan berterima kasih atas komentar Anda dengan pro dan kontra yang beralasan dari pendekatan ini, serta untuk saran alternatif yang telah diuji.

Referensi

  • Mengatur Ulang dan Membangun Kembali Indeks
  • sys.dm_db_index_physical_stats

Alat yang berguna:

dbForge Index Manager – add-in SSMS yang berguna untuk menganalisis status indeks SQL dan memperbaiki masalah dengan fragmentasi indeks.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. INSTR() Setara di SQL Server

  2. Cara Mengonversi Stempel Waktu Unix ke Nilai Tanggal/Waktu di SQL Server

  3. Bagaimana cara menulis karakter UTF-8 menggunakan penyisipan massal di SQL Server?

  4. 3 Cara Mengembalikan Semua Tabel TANPA Kunci Utama di SQL Server

  5. Bagaimana saya bisa MEMASUKKAN data ke dalam dua tabel secara bersamaan di SQL Server?