Block columns of different heights with a ruler, representing measuring table sizes in SQL Server

SQL Server’da Tablo Boyutlarını Bulma: Satır Sayısı, Veri, Index ve Boş Alan

SQL Server’da tablo boyutlarını veri, index ve boş alan olarak ayıran sorgular, tüm veritabanlarında en büyük tablolar, sonuçların yorumlanması ve sıkıştırmanın sağlayacağı kazanç.

Temmuz 18, 2023

Disk dolmaya başladığında, yedekler uzadığında ya da bir veritabanının neden bu kadar büyüdüğü sorulduğunda cevap genellikle birkaç büyük tabloda saklıdır. Hangi tablonun ne kadar yer kapladığını, bu alanın ne kadarının veri, ne kadarının index ve ne kadarının boşta beklediğini bilmek; arşivleme, sıkıştırma ve kapasite kararlarının başlangıç noktasıdır.

Bu yazıda tablo boyutlarını doğru hesaplayan sorguları, tüm veritabanlarında en büyük tabloları bulmayı ve sonuçları nasıl yorumlayacağınızı anlatıyoruz.

SQL Server Danışmanlığı

Veritabanınız beklenenden hızlı mı büyüyor?

Aryasoft, büyümenin kaynağını tablo ve index düzeyinde bulur; arşivleme, sıkıştırma ve kapasite planını birlikte hazırlar.

Destek Alın

Tablo Boyutlarını Hesaplayan Sorgu

En güvenilir kaynak sys.dm_db_partition_stats görünümüdür. Her partition için ayrılan (reserved) ve kullanılan (used) sayfa sayılarını tutar; bir sayfa 8 KB’tır. Aşağıdaki sorgu her tablo için satır sayısını, toplam ayrılan alanı ve bu alanın veri, index ve kullanılmayan kısımlarını megabayt olarak verir:

SELECT TOP (50)
       s.name + N'.' + t.name AS table_name,
       SUM(CASE WHEN ps.index_id IN (0, 1) THEN ps.row_count ELSE 0 END)  AS row_count,
       SUM(ps.reserved_page_count) * 8 / 1024.0                           AS reserved_mb,
       SUM(CASE WHEN ps.index_id IN (0, 1)
                THEN ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count
                ELSE 0 END) * 8 / 1024.0                                  AS data_mb,
       SUM(CASE WHEN ps.index_id > 1 THEN ps.used_page_count ELSE 0 END) * 8 / 1024.0 AS nonclustered_index_mb,
       SUM(ps.reserved_page_count - ps.used_page_count) * 8 / 1024.0      AS unused_mb
FROM sys.dm_db_partition_stats AS ps
JOIN sys.tables  AS t ON t.object_id = ps.object_id
JOIN sys.schemas AS s ON s.schema_id = t.schema_id
GROUP BY s.name, t.name
ORDER BY reserved_mb DESC;

Bu sorgu SQL Server’ın meta verisinden okur; tabloları taramaz ve üretim ortamında güvenle çalıştırılabilir. index_id 0 heap’i, 1 clustered index’i (yani tablonun verisini), 1’den büyük değerler nonclustered index’leri temsil eder.

Not

sys.dm_db_partition_stats içindeki row_count, Microsoft’un ifadesiyle yaklaşık bir değerdir; çoğu durumda doğrudur ama tam sayım gerektiren raporlarda COUNT_BIG(*) kullanın. Kapasite analizi için yaklaşık değer fazlasıyla yeterlidir.

Sonuçları Nasıl Yorumlamalı?

  • data_mb büyük, nonclustered_index_mb küçük: Tablonun kendisi büyüktür. Arşivleme, partitioning ya da sıkıştırma adayıdır.
  • nonclustered_index_mb, data_mb’ye yakın ya da büyük: Tabloda çok sayıda ya da çok geniş index vardır. Kullanılmayan ve tekrarlanan index’leri kontrol edin; ayrıntıları index rehberimizde anlatıyoruz.
  • unused_mb yüksek: Tabloya ayrılmış ama kullanılmayan alan vardır. Büyük silmelerden sonra heap’lerde sık görülür.
  • LOB sayfaları belirgin: lob_used_page_count yüksekse, nvarchar(max), varbinary(max) ya da XML kolonlarında büyük belgeler veya dosyalar saklanıyordur; bunların veritabanı dışında tutulması değerlendirilebilir.

Uyarı

Heap tablolarda (clustered index’i olmayan) DELETE ile boşalan sayfalar her zaman serbest bırakılmaz; tablo, içindeki satır sayısı azalsa bile aynı alanı kaplamaya devam edebilir. Bu alanı geri kazanmanın kalıcı yolu tabloya uygun bir clustered index eklemek ya da ALTER TABLE … REBUILD çalıştırmaktır. Veritabanı dosyasını shrink etmek bu sorunu çözmez.

Tek Bir Tablo İçin: sp_spaceused

Hızlı bir kontrol için sp_spaceused yeterlidir. Tablo adıyla çağrıldığında satır sayısını ve ayrılan, veri, index ve kullanılmayan alanı döndürür; parametresiz çağrıldığında veritabanı genelindeki durumu verir:

EXEC sys.sp_spaceused N'dbo.Siparis';
EXEC sys.sp_spaceused;   -- veritabanı geneli

SSMS’te veritabanına sağ tıklayıp Reports › Standard Reports › Disk Usage by Top Tables raporu da aynı bilgiyi grafik olarak sunar.

Tüm Veritabanlarında En Büyük Tablolar

Bir sunucudaki tüm veritabanlarında en büyük tabloları bulmak için sorguyu her veritabanında çalıştırıp sonuçları tek bir tabloda toplayabilirsiniz:

IF OBJECT_ID(N'tempdb..#TableSizes') IS NOT NULL DROP TABLE #TableSizes;
CREATE TABLE #TableSizes (database_name sysname, table_name nvarchar(300),
                          row_count bigint, reserved_mb decimal(18, 2));

DECLARE @db sysname, @sql nvarchar(max);
DECLARE dbs CURSOR LOCAL FAST_FORWARD FOR
    SELECT name FROM sys.databases
    WHERE state_desc = N'ONLINE' AND database_id > 4;

OPEN dbs;
FETCH NEXT FROM dbs INTO @db;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = N'USE ' + QUOTENAME(@db) + N';
        SELECT DB_NAME(), s.name + N''.'' + t.name,
               SUM(CASE WHEN ps.index_id IN (0, 1) THEN ps.row_count ELSE 0 END),
               SUM(ps.reserved_page_count) * 8 / 1024.0
        FROM sys.dm_db_partition_stats AS ps
        JOIN sys.tables  AS t ON t.object_id = ps.object_id
        JOIN sys.schemas AS s ON s.schema_id = t.schema_id
        GROUP BY s.name, t.name;';
    INSERT INTO #TableSizes EXEC sys.sp_executesql @sql;
    FETCH NEXT FROM dbs INTO @db;
END
CLOSE dbs;
DEALLOCATE dbs;

SELECT TOP (50) * FROM #TableSizes ORDER BY reserved_mb DESC;

Döngü kalıplarının farklarını ve ne zaman WHILE ile kuyruk tablosu kullanmanın daha esnek olduğunu cursor rehberimizde anlatıyoruz.

Sıkıştırma Ne Kazandırır?

Büyük tablolarda veri sıkıştırma, hem disk alanını hem de okunan sayfa sayısını azaltabilir. Uygulamadan önce kazancı tahmin edin:

EXEC sys.sp_estimate_data_compression_savings
     @schema_name = N'dbo', @object_name = N'Siparis',
     @index_id = NULL, @partition_number = NULL, @data_compression = N'PAGE';

İpucu

Tablo boyutlarını düzenli olarak (örneğin haftalık) bir tabloya kaydedin. Tek bir anlık görüntü hangi tablonun büyük olduğunu söyler; zaman içindeki kayıtlar ise hangisinin hızla büyüdüğünü gösterir ve kapasite planını tahminden çıkarıp ölçüme dayandırır.

Kontrol Listesi

  • En büyük tablolar ve veri / index / boş alan dağılımı biliniyor.
  • Index alanı veriye yakın tablolarda kullanılmayan index’ler incelendi.
  • Büyük boş alan taşıyan heap’ler için clustered index ya da rebuild planlandı.
  • Büyük tablolar için sıkıştırma kazancı tahmin edildi.
  • Boyutlar düzenli kaydedilip büyüme trendi izleniyor.
sys.dm_db_partition_stats görünümündeki reserved_page_count ve used_page_count değerlerini 8 ile çarparak KB cinsinden boyutu hesaplayabilirsiniz. Tek bir tablo için sp_spaceused da yeterlidir.
Evet. sys.dm_db_partition_stats meta veriden okur ve tabloları taramaz; yük oluşturmaz.
Özellikle heap tablolarda boşalan sayfalar serbest bırakılmayabilir. Tabloya clustered index eklemek ya da ALTER TABLE … REBUILD çalıştırmak alanı geri kazandırır.
Tabloya ayrılmış ama henüz kullanılmayan extent’ler ya da büyük silmelerden sonra boşalan alan unused olarak görünür. Heap’lerde ve sık silme yapılan tablolarda daha belirgindir.

SQL Server Danışmanlığı

Büyümeyi tahminle değil, ölçümle yönetin

Aryasoft’un kıdemli DBA ekibi tablo ve index düzeyinde büyümeyi analiz eder; arşivleme, sıkıştırma, index temizliği ve kapasite planını birlikte hazırlar.

4.7/5