Tablolarımız üzerinde bulunan indexler zamanla çalışan sorgular neticesinde bozulmalara uğramaktadır. Bu indexlerin belirli periyotlarla rebuild veya reorganize edilmesi gerekir. %5 ile %30 arası bozulmalarda reorganize %30 üzeri bozulmalarda ise rebuild işlemi yapılması Microsoft'un meşhur deyimi ile Best Practicedir.
Yukarıdada bahsettiğim gibi oluşturduğumuz indexlerde veri eklenmesi silinmesi gibi işlemler oldukça indexlerimiz pageleri arasında boşluklar oluşacak ve btree veri yapımızın dengesi bozulacaktır. Bu nedenle düzenli olarak bozulan indexlerimizi bulup bozulma oranlarına göre rebuild veya reorganize etmemiz gerekir.
Aşağıdaki DMV kullanılarak indexlerideki bozulma oranlarını görebiliriz.
SELECT TOP 200
DB_NAME() AS databaseName
,OBJECT_SCHEMA_NAME(s.object_id) AS SchemaName
, OBJECT_NAME(s.[object_id]) As TableName
,i.name As IndexName
,ROUND(s.avg_fragmentation_in_percent,2) AS [Fragmentation %]
FROM sys.dm_db_index_physical_stats(db_id(),null,null,null,null)
s
INNER JOIN sys.indexes i on s.[object_id] =i.[object_id]
and s.index_id=i.index_id
INNER JOIN sys.indexes o on i.object_id=o.object_id
WHERE s.database_id=DB_ID()
and i.name is not null
and OBJECTPROPERTY(s.[object_id],'IsMsShipped')=0
order by [Fragmentation %] desc
Bu bozulma oranlarını gördükten sonra çeşitli yöntemlerle index bakımı yapabiliriz. Aşağıdaki scriptte cursor kullanarak index bakımını çok kolaylıkla yapabiliriz.
DECLARE
@Database VARCHAR(255)
DECLARE
@Table VARCHAR(255)
DECLARE
@cmd NVARCHAR(500)
DECLARE
@fillfactor INT
SET
@fillfactor = 30
DECLARE
DatabaseCursor CURSOR FOR
SELECT
name FROM master.dbo.sysdatabases
WHERE
name IN ('SAROT_OTEL')
ORDER BY 1
OPEN
DatabaseCursor
FETCH NEXT FROM
DatabaseCursor INTO @Database
WHILE @@FETCH_STATUS =
0
BEGIN
SET @cmd = 'DECLARE TableCursor CURSOR
FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' +
table_name + '']'' as tableName FROM [' + @Database + '].INFORMATION_SCHEMA.TABLES
WHERE table_type = ''BASE TABLE'''
-- create table
cursor
EXEC (@cmd)
OPEN
TableCursor
FETCH NEXT FROM TableCursor
INTO @Table
WHILE @@FETCH_STATUS =
0
BEGIN
IF (@@MICROSOFTVERSION
/ POWER(2, 24) >= 9)
BEGIN
-- SQL
2005 or higher command
SET
@cmd = 'ALTER INDEX ALL
ON ' + @Table +
' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ')'
EXEC (@cmd)
END
ELSE
BEGIN
-- SQL 2000
command
DBCC
DBREINDEX(@Table,' ',@fillfactor)
END
FETCH NEXT FROM TableCursor
INTO @Table
END
CLOSE
TableCursor
DEALLOCATE
TableCursor
FETCH NEXT FROM
DatabaseCursor INTO @Database
END
CLOSE
DatabaseCursor
DEALLOCATE
DatabaseCursor