MSSQL Server Duplica Index Bulma Komutu

Bu makalede veritabanı altında bulunan tabloların üzerinde bulunan benzer index yapılarını göstermektedir. Bu komut yardımıyla aynı index yapılarımızı kullanıp kullanılmadığına göre silinmesi gerekmektedir. SQL Server’da bir tabloda aynı veya benzer index yapılarının birden fazla kez oluşturulması, sistem performansını ve kaynak kullanımını olumsuz etkileyebilir.

Bunun neden olduğu etkiler ve potansiyel sonuçları;

– Her indeks, fiziksel olarak disk alanında yer kaplar. Aynı veya benzer indeksler oluşturulduğunda, gereksiz yere depolama alanı tüketilir. Özellikle büyük tablolarda bu durum ciddi disk alanı problemlerine yol açabilir.

– Bir tabloya veri ekleme, güncelleme veya silme işlemleri sırasında SQL Server, tüm ilgili indeksleri güncellemek zorundadır. Benzer indekslerin birden fazla kez olması, her yazma işlemini daha maliyetli hale getirir ve işlem süresini artırır.

-Sorgu planlayıcı (Query Optimizer), hangi indeksi kullanacağına karar verirken birden fazla benzer indeksle karşılaşabilir. Bu durum sorgu planının gereksiz karmaşık hale gelmesine ve doğru indeksi seçememe ihtimaline yol açabilir. Aynı zamanda, yanlış indeksin seçilmesi sorgu performansını düşürebilir.

– İndekslerin yönetimi (örneğin, yeniden oluşturma, yeniden düzenleme) ve bakım işlemleri sırasında gereksiz indeksler, işlem süresini ve bakım maliyetlerini artırır. İndeks bakımının sık yapılmadığı sistemlerde, bu durum zamanla performans sorunlarına yol açabilir.

– Her indeks, sorgu yürütme sırasında bellekte ek yer gerektirir. Aynı veya benzer indekslerin olması, gereksiz bellek tüketimi ve daha fazla disk I/O işlemi anlamına gelir.

– Benzer indekslerin olması, SQL Server’ın verileri birden fazla yerde saklamasına neden olur. Bu, indekslerdeki fragmentasyon (parçalanma) problemlerini artırabilir ve performans kaybına yol açabilir.

Bu tarz indexlerin oluşturulmasının sebeplerinden önceliği sql server yapımızın her önerdiği indexin oluşturulması veya veritabanının birden fazla kişi tarafından kullanılması bu sorunun en önemli sebeplerindendir.

Aşağıdaki komut sayesinde veritabanı altında bulunan duplica indexsleri bulabiliriz. Aynı zamanda indexsin hangi tür olduğu, boyutu, ismi, indexsin etkilediği satır sayısını görebiliriz.

WITH IndexColumns AS (
    SELECT 
        DB_NAME() AS database_name,  -- Veritabanı Adı
        s.name AS schema_name,       -- Şema Adı
        t.name AS table_name,        -- Tablo Adı
        i.name AS index_name,        -- Index Adı
        i.index_id,
        i.type_desc AS index_type,   -- Index Türü (Clustered / NonClustered)
        SUM(ps.used_page_count) * 8 / 1024.0 AS index_size_mb, -- Index Boyutu (MB)
        p.rows AS index_row_count,   -- Indexteki Satır Sayısı
        STRING_AGG(c.name, ', ') WITHIN GROUP (ORDER BY ic.key_ordinal) AS indexed_columns -- Indexlenen Kolonlar
    FROM sys.schemas s
    JOIN sys.tables t ON s.schema_id = t.schema_id
    JOIN sys.indexes i ON t.object_id = i.object_id
    JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
    JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
    JOIN sys.dm_db_partition_stats ps ON p.object_id = ps.object_id AND p.index_id = ps.index_id
    WHERE i.type IN (1, 2) -- Sadece Clustered ve Non-Clustered Indexler
    GROUP BY s.name, t.name, i.index_id, i.name, i.type_desc, p.rows
)
SELECT 
    i1.database_name,
    i1.schema_name,
    i1.table_name,
    i1.index_name AS duplicate_index, -- Sonradan oluşturulan Duplicate Index
    i2.index_name AS original_index,  -- İlk oluşturulan Index
    i1.index_type,
    i1.indexed_columns, 
    i1.index_row_count,
    i1.index_size_mb AS duplicate_index_size_mb, -- Duplicate Index'in Boyutu
    i2.index_size_mb AS original_index_size_mb   -- Orijinal Index'in Boyutu
FROM IndexColumns i1
JOIN IndexColumns i2 
    ON i1.database_name = i2.database_name
    AND i1.schema_name = i2.schema_name
    AND i1.table_name = i2.table_name
    AND i1.index_id > i2.index_id 
    AND i1.indexed_columns = i2.indexed_columns
    AND i1.index_type = i2.index_type -- Aynı türdeki indexleri karşılaştırır
ORDER BY i1.database_name, i1.schema_name, i1.table_name, i1.indexed_columns;

İndexlerle ilgili genel duruma bakıldıktan sonra aşağıdaki komut ile ilgili index silinebilir.

DROP INDEX IndexName ON TableName;

Yada indexsin disable edilmesi gerekmektedir.

ALTER INDEX [IndexName ] ON [dbo].[TableName] DISABLE;

Tüm instance altında bulunan veritabanları için bu değerin dönülmesi isteniyorsa aşağıdaki komut kullanılır.

DECLARE @command nvarchar(max) 
SELECT @command = 'USE [?] 
;WITH IndexColumns AS (
    SELECT 
        DB_NAME() AS database_name,  -- Veritabanı Adı
        s.name AS schema_name,       -- Şema Adı
        t.name AS table_name,        -- Tablo Adı
        i.name AS index_name,        -- Index Adı
        i.index_id,
        i.type_desc AS index_type,   -- Index Türü (Clustered / NonClustered)
        SUM(ps.used_page_count) * 8 / 1024.0 AS index_size_mb, -- Index Boyutu (MB)
        p.rows AS index_row_count,   -- Indexteki Satır Sayısı
        STRING_AGG(c.name, '', '') WITHIN GROUP (ORDER BY ic.key_ordinal) AS indexed_columns -- Indexlenen Kolonlar
    FROM sys.schemas s
    JOIN sys.tables t ON s.schema_id = t.schema_id
    JOIN sys.indexes i ON t.object_id = i.object_id
    JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
    JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
    JOIN sys.dm_db_partition_stats ps ON p.object_id = ps.object_id AND p.index_id = ps.index_id
    WHERE i.type IN (1, 2) -- Sadece Clustered ve Non-Clustered Indexler
    GROUP BY s.name, t.name, i.index_id, i.name, i.type_desc, p.rows
)
SELECT 
    i1.database_name,
    i1.schema_name,
    i1.table_name,
    i1.index_name AS duplicate_index, -- Sonradan oluşturulan Duplicate Index
    i2.index_name AS original_index,  -- İlk oluşturulan Index
    i1.index_type,
    i1.indexed_columns, 
    i1.index_row_count,
    i1.index_size_mb AS duplicate_index_size_mb, 
    i2.index_size_mb AS original_index_size_mb   
FROM IndexColumns i1
JOIN IndexColumns i2 
    ON i1.database_name = i2.database_name
    AND i1.schema_name = i2.schema_name
    AND i1.table_name = i2.table_name
    AND i1.index_id > i2.index_id 
    AND i1.indexed_columns = i2.indexed_columns
    AND i1.index_type = i2.index_type -- Aynı türdeki indexleri karşılaştırır
ORDER BY i1.database_name, i1.schema_name, i1.table_name, i1.indexed_columns;'
EXEC sp_MSforeachdb @command 

Sonuç olarak;

Aynı indeks yapılarının birden fazla kez oluşturulması, sorgu performansı, yazma işlemleri ve disk alanı üzerinde olumsuz etkiler yaratır. Düzenli analiz ve bakım yaparak gereksiz indekslerden kaçınmak, sistemin hem verimli çalışmasını sağlar hem de kaynak kullanımını optimize eder.

Bu makalede mssql server yapımızda duplica index bulma komutlarını görmüş olduk. Başka bir makalede görüşmek dileğiyle..

“Allah’ın, göklerde ve yerde bulunan şeyleri hizmetinize verdiğini, nimetlerini gizli ve açık olarak önünüze bolca serdiğini görmez misiniz? İnsanlardan öyleleri vardır ki bir bilgi, bir rehber ve aydınlatıcı bir kitap olmadan Allah hakkında tartışmaya kalkışırlar.”Lokman-20

Author: Yunus YÜCEL

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir