Bagaimana cara menemukan objek terbesar dalam database SQL Server?

138

Bagaimana cara menemukan objek terbesar dalam database SQL Server? Pertama, dengan menentukan tabel mana (dan indeks terkait) yang terbesar dan kemudian menentukan baris mana dalam tabel tertentu yang terbesar (kami menyimpan data biner dalam BLOB)?

Apakah ada alat di luar sana untuk membantu analisis database semacam ini? Atau apakah ada beberapa kueri sederhana yang dapat saya jalankan terhadap tabel sistem?

jamesaharvey
sumber

Jawaban:

290

Saya telah menggunakan skrip SQL ini (yang saya dapatkan dari seseorang, di suatu tempat - tidak dapat merekonstruksi dari siapa asalnya) selama berabad-abad dan ini membantu saya sedikit memahami dan menentukan ukuran indeks dan tabel:

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) 

Tentu saja, Anda dapat menggunakan kriteria pemesanan lain, misalnya

ORDER BY SUM(p.rows) DESC

untuk mendapatkan tabel dengan baris terbanyak, atau

ORDER BY SUM(a.total_pages) DESC

untuk mendapatkan tabel dengan halaman terbanyak (8K blok) digunakan.

marc_s
sumber
Luar biasa terima kasih! Sekarang, setelah saya mempersempit objek terbesar saya ke tabel yang berisi banyak data biner, untuk mencari tahu baris mana dari data biner yang terbesar?
jamesaharvey
3
untuk itu, Anda harus memilih pada tabel itu dan mencetak DATALENGTH (bidang) untuk setiap bidang yang Anda minati (biasanya VARCHAR (MAX), VARBINARY (MAX) dan sebagainya)
marc_s
1
Terima kasih @marc_s, ini sangat berguna. Kolom TableName juga dapat menyertakan nama skema denganSELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen
2
Itu pasti skrip TSQL terindah yang pernah saya lihat
Agustin Meriles
2
Untuk menyertakan indeks NON-CLUSTERED juga, hapus "dan i.index_id <= 1" dari klausa WHERE.
Gordon Bell
72

Di SQL Server 2008, Anda juga dapat menjalankan laporan standar Penggunaan Disk menurut Tabel Teratas. Ini dapat ditemukan dengan mengklik kanan DB, memilih Laporan-> Laporan Standar dan memilih laporan yang Anda inginkan.

Gregory Lancaster
sumber
8
Tidak bercanda? Itu adalah jawaban yang revolusioner. Terima kasih telah mempostingnya. (Bukan sarkasme. Telah menjalankan kueri ini secara manual untuk sementara waktu sekarang dan saya tidak percaya laporan ini sudah ada!)
Jennifer Zouak
4

Kueri ini membantu menemukan tabel terbesar di koneksi Anda.

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
Vinoth_S
sumber
Ada baiknya memiliki sesuatu yang mudah kita hafal. Terima kasih atas keringkasannya.
David Betz
3

Anda juga dapat menggunakan kode berikut:

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
Dheeraj Bansal
sumber
2

Jika Anda menggunakan Sql Server Management Studio 2008 ada bidang data tertentu yang dapat Anda lihat di jendela rincian objek explorer. Cukup telusuri dan pilih folder tabel. Dalam tampilan detail Anda dapat mengklik kanan judul kolom dan menambahkan kolom ke "laporan". Jarak tempuh Anda mungkin berbeda jika Anda menggunakan SSMS 2008 express.

doug_w
sumber
2

Saya telah menemukan kueri ini juga sangat membantu di SqlServerCentral, berikut adalah tautan ke posting asli

Tabel terbesar Sql Server

  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   

Dalam database saya, mereka memberikan hasil yang berbeda antara kueri ini dan jawaban pertama.

Semoga seseorang menemukan berguna

Franco
sumber
1

Jawaban @ marc_s sangat bagus dan saya telah menggunakannya selama beberapa tahun. Namun, saya perhatikan bahwa skrip melewatkan data di beberapa indeks toko kolom dan tidak menunjukkan gambaran lengkap. Misalnya, ketika Anda melakukan SUM(TotalSpace)melawan skrip dan membandingkannya dengan properti database ruang total di Studio Manajemen, angkanya tidak cocok dalam kasus saya (Studio Manajemen menunjukkan angka yang lebih besar). Saya memodifikasi skrip untuk mengatasi masalah ini dan memperpanjangnya sedikit:

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

Semoga bermanfaat bagi seseorang. Skrip ini telah diuji terhadap database berukuran TB yang besar dengan ratusan tabel, indeks, dan skema yang berbeda.

dyatchenko
sumber