SQL Server veritabanındaki en büyük nesneleri nasıl bulabilirim?


136

Bir SQL Server veritabanındaki en büyük nesneleri nasıl bulabilirim? Birincisi, hangi tabloların (ve ilgili endekslerin) en büyük olduğunu belirledikten sonra belirli bir tablodaki hangi satırların en büyük olduğunu belirleyerek (ikili verileri BLOB'larda depolarız)?

Bu tür bir veritabanı analizine yardımcı olacak herhangi bir araç var mı? Yoksa sistem tablolarına karşı çalıştırabileceğim bazı basit sorgular var mı?

Yanıtlar:


280

Bu SQL betiğini (ki bir yerden, bir yerden aldım - kimden geldiğini yeniden inşa edemiyorum) kullanıyorum ve bana oldukça biraz anlayış ve endekslerin ve tabloların boyutunu belirlemeye yardımcı oldu:

SELECT 
    t.name AS TableName,
    i.name as indexName,
    sum(p.rows) as RowCounts,
    sum(a.total_pages) as TotalPages, 
    sum(a.used_pages) as UsedPages, 
    sum(a.data_pages) as DataPages,
    (sum(a.total_pages) * 8) / 1024 as TotalSpaceMB, 
    (sum(a.used_pages) * 8) / 1024 as UsedSpaceMB, 
    (sum(a.data_pages) * 8) / 1024 as DataSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.object_id = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
WHERE 
    t.name NOT LIKE 'dt%' AND
    i.object_id > 255 AND  
    i.index_id <= 1
GROUP BY 
    t.name, i.object_id, i.index_id, i.name 
ORDER BY 
    object_name(i.object_id) 

Elbette, başka bir sipariş kriteri de kullanabilirsiniz, örn.

ORDER BY SUM(p.rows) DESC

en fazla satır içeren tabloları almak için veya

ORDER BY SUM(a.total_pages) DESC

en fazla sayfa (8K blok) kullanılan tabloları almak için.


Harika teşekürler! Şimdi, en büyük nesnemi, ikili veri satırlarından hangisinin en büyük olduğunu anlamak için, çok sayıda ikili veri içeren bir tabloya daralttığım için?
jamesaharvey

3
bunun için, bu tabloda bir seçim yapmanız ve ilgilendiğiniz her alan için DATALENGTH (alan) yazdırmanız gerekir (genellikle VARCHAR (MAX), VARBINARY (MAX) vb.)
marc_s

1
Teşekkürler @marc_s, bu çok faydalı oldu. TableName sütununda şema adı da bulunabilirSELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen

2
Bu şimdiye kadar gördüğüm en güzel TSQL betiği olmalı
Agustin Meriles

2
CLUSTERED olmayan dizinleri de dahil etmek için, WHERE yan tümcesinden "ve i.index_id <= 1" öğelerini kaldırın.
Gordon Bell

72

SQL Server 2008'de, Üst Tablolara Göre Standart Disk Kullanımı raporunu da çalıştırabilirsiniz. Bu, DB'yi sağ tıklayıp Raporlar-> Standart Raporlar'ı seçerek ve istediğiniz raporu seçerek bulunabilir.


8
Şaka yapmıyorum? Bu devrimci bir cevap. Gönderdiğiniz için teşekkürler. (İğneleyici değil. Bu sorguları bir süredir manuel olarak çalıştırıyorum ve bu raporların zaten orada olduğuna inanamıyorum!)
Jennifer Zouak

4

Bu sorgu, bağlantınızdaki en büyük tabloyu bulmanıza yardımcı olur.

SELECT  TOP 1 OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

Kolayca ezberleyebileceğimiz bir şeye sahip olmak güzel. Özlü için teşekkürler.
David Betz

3

Aşağıdaki kodu da kullanabilirsiniz:

USE AdventureWork
GO
CREATE TABLE #GetLargest 
(
  table_name    sysname ,
  row_count     INT,
  reserved_size VARCHAR(50),
  data_size     VARCHAR(50),
  index_size    VARCHAR(50),
  unused_size   VARCHAR(50)
)

SET NOCOUNT ON

INSERT #GetLargest

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT 
  a.table_name,
  a.row_count,
  COUNT(*) AS col_count,
  a.data_size
  FROM #GetLargest a
     INNER JOIN information_schema.columns b
     ON a.table_name collate database_default
     = b.table_name collate database_default
       GROUP BY a.table_name, a.row_count, a.data_size
       ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC

DROP TABLE #GetLargest

2

Sql Server Management Studio 2008 kullanıyorsanız, nesne gezgini ayrıntıları penceresinde görüntüleyebileceğiniz belirli veri alanları vardır. Sadece tablolar klasörüne göz atın ve seçin. Ayrıntılar görünümünde sütun başlıklarını sağ tıklayıp "rapor" a alanlar ekleyebilirsiniz. SSMS 2008 ekspresindeyseniz kilometreniz değişebilir.


2

Bu sorguyu da SqlServerCentral'da çok yararlı buldum, işte orijinal yazının bağlantısı

Sql Server en büyük tabloları

  select name=object_schema_name(object_id) + '.' + object_name(object_id)
, rows=sum(case when index_id < 2 then row_count else 0 end)
, reserved_kb=8*sum(reserved_page_count)
, data_kb=8*sum( case 
     when index_id<2 then in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count 
     else lob_used_page_count + row_overflow_used_page_count 
    end )
, index_kb=8*(sum(used_page_count) 
    - sum( case 
           when index_id<2 then in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count 
        else lob_used_page_count + row_overflow_used_page_count 
        end )
     )    
, unused_kb=8*sum(reserved_page_count-used_page_count)
from sys.dm_db_partition_stats
where object_id > 1024
group by object_id
order by 
rows desc   

Veritabanımda bu sorgu ile 1. cevap arasında farklı sonuçlar verdiler.

Umarım birisi faydalı bulur


1

@ marc_s'ın cevabı çok güzel ve birkaç yıldır kullanıyorum. Ancak, komut dosyasının bazı sütun deposu dizinlerindeki verileri özlediğini ve tam resmi göstermediğini fark ettim. SUM(TotalSpace)Komut dosyasına karşı yaptığınızda ve Management Studio'daki toplam alan veritabanı özelliği ile karşılaştırdığınızda, sayılar benim durumumda uyuşmuyor (Management Studio daha büyük sayılar gösteriyor). Bu sorunun üstesinden gelmek için komut dosyasını değiştirdim ve biraz uzattım:

select
    tables.[name] as table_name,
    schemas.[name] as schema_name,
    isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown') as database_name,
    sum(allocation_units.total_pages) * 8 as total_space_kb,
    cast(round(((sum(allocation_units.total_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as total_space_mb,
    sum(allocation_units.used_pages) * 8 as used_space_kb,
    cast(round(((sum(allocation_units.used_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as used_space_mb,
    (sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8 as unused_space_kb,
    cast(round(((sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8) / 1024.00, 2) as numeric(36, 2)) as unused_space_mb,
    count(distinct indexes.index_id) as indexes_count,
    max(dm_db_partition_stats.row_count) as row_count,
    iif(max(isnull(user_seeks, 0)) = 0 and max(isnull(user_scans, 0)) = 0 and max(isnull(user_lookups, 0)) = 0, 1, 0) as no_reads,
    iif(max(isnull(user_updates, 0)) = 0, 1, 0) as no_writes,
    max(isnull(user_seeks, 0)) as user_seeks,
    max(isnull(user_scans, 0)) as user_scans,
    max(isnull(user_lookups, 0)) as user_lookups,
    max(isnull(user_updates, 0)) as user_updates,
    max(last_user_seek) as last_user_seek,
    max(last_user_scan) as last_user_scan,
    max(last_user_lookup) as last_user_lookup,
    max(last_user_update) as last_user_update,
    max(tables.create_date) as create_date,
    max(tables.modify_date) as modify_date
from 
    sys.tables
    left join sys.schemas on schemas.schema_id = tables.schema_id
    left join sys.indexes on tables.object_id = indexes.object_id
    left join sys.partitions on indexes.object_id = partitions.object_id and indexes.index_id = partitions.index_id
    left join sys.allocation_units on partitions.partition_id = allocation_units.container_id
    left join sys.dm_db_index_usage_stats on tables.object_id = dm_db_index_usage_stats.object_id and indexes.index_id = dm_db_index_usage_stats.index_id
    left join sys.dm_db_partition_stats on tables.object_id = dm_db_partition_stats.object_id and indexes.index_id = dm_db_partition_stats.index_id
group by schemas.[name], tables.[name], isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown')
order by 5 desc

Birisi için yararlı olacağını umuyoruz. Bu komut dosyası, yüzlerce farklı tablo, dizin ve şema içeren TB genelindeki büyük veritabanlarına karşı test edilmiştir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.