Dapatkan ukuran semua tabel dalam database

1271

Saya telah mewarisi database SQL Server yang cukup besar. Tampaknya mengambil lebih banyak ruang daripada yang saya harapkan, mengingat data yang dikandungnya.

Apakah ada cara mudah untuk menentukan berapa banyak ruang pada disk yang dikonsumsi setiap tabel?

Eric
sumber
peran apa yang bisa Anda akses? Apakah Anda DBA, atau apakah ini dikelola melalui host web, klien, atau sejenisnya?
Rob Allen
kemungkinan duplikat ukuran Tabel dan Indeks di SQL Server
Joe Stefanelli
@Roballen Saya memiliki akses penuh ke database, jadi skrip yang memerlukan peran apa pun sudah cukup.
Eric
Untuk Azure saya menggunakan ini
Irf

Jawaban:

2594
SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
    CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
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
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    TotalSpaceMB DESC, t.Name
marc_s
sumber
7
Pertanyaan konyol, tetapi apakah mungkin bahwa kueri ini dapat menyebabkan penguncian baris?
GEMI
7
Indeks juga menggunakan ruang, dan jumlah ruang yang digunakan oleh indeks dapat ditemukan dengan permintaan ini di bawah.
Jens Frandsen
6
Skrip Anda memiliki masalah dengan indeks yang difilter: Untuk setiap indeks yang difilter untuk tabel tertentu, saya melihat baris tambahan dengan nama tabel di hasil. "RowCounts" dari masing-masing baris tambahan tersebut sesuai dengan jumlah baris yang dicakup oleh salah satu indeks yang difilter. (pada Sql2012)
Akos Lukacs
37
@Todd: beberapa orang menginginkannya dipesan seperti itu - yang lain menginginkannya berdasarkan nama tabel - pilihlah, sesuaikan kode sesuai kebutuhan ....
marc_s
12
Jika tabel Anda dipartisi, mereka muncul beberapa kali tanpa ada indikasi apa yang sedang terjadi. Anda dapat menambahkan p.partition_number ke daftar pilih atau Anda dapat SUM (p.Rows) dan menghapusnya dari grup dengan.
PRMan
561

Jika Anda menggunakan SQL Server Management Studio (SSMS), alih-alih menjalankan kueri ( yang dalam kasus saya mengembalikan baris duplikat ), Anda dapat menjalankan laporan standar

  1. Klik kanan pada database
  2. Navigasikan ke Laporan> Laporan Standar> Penggunaan Disk Menurut Tabel

Catatan: Tingkat kompatibilitas basis data harus diatur ke 90 atau di atasnya agar ini berfungsi dengan benar. Lihat http://msdn.microsoft.com/en-gb/library/bb510680.aspx

Kevin Brydon
sumber
54
Di Management Studio 2012 Anda dapat melakukan: Rincian Tampilan-Obyek Explorer (F7) dan menavigasi ke "Tabel" di Object Explorer. Dalam Rincian klik kanan pada header dan pilih kolom ukuran.
ValGe
3
untuk menasihati fungsionalitas baru dengan SSMS 2012. Bagi kami orang tua, kami tidak pernah memiliki ini tersedia. Jadi kami baru saja melakukannya dengan cara TSQL lama :)
GoldBishop
3
Percaya atau tidak, kadang-kadang orang biasa (pengembang) ingin melihat info ini dan kami tidak memiliki izin untuk menggunakan laporan bawaan tetapi kami dapat menjalankan TSQL dalam jawaban yang diterima. :) FYI (BTW, saya masih mengangkat jawaban Anda)
Andrew Steitz
8
Tampaknya tidak hadir dalam Azure SQL :-(
Simon_Weaver
1
Saya tahu ini tidak serius, tapi tolong tolong singkirkan kelompok-kelompok yang terpinggirkan dari teknik & teknologi dengan alasan ini diulangi di mana-mana. Anda harus mempelajari keduanya, tetapi Anda tidak harus menghukum orang karena menggunakan utilitas hemat waktu untuk bekerja lebih pintar dan lebih cepat. (Meskipun SSMS tampaknya menjadi "utilitas melambat" kadang-kadang ...: X) Secara pribadi pembacaan untuk data tabular biasanya lebih jelas dalam GUI, meskipun alat buatan Microsoft cenderung menjadi pengecualian untuk semua yang terkait dengan UI.
Julia McGuigan
102

sp_spaceused dapat memberi Anda informasi tentang ruang disk yang digunakan oleh tabel, tampilan indeks, atau seluruh database.

Sebagai contoh:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

Ini melaporkan informasi penggunaan disk untuk tabel ContactInfo.

Untuk menggunakan ini untuk semua tabel sekaligus:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

Anda juga bisa mendapatkan penggunaan disk dari dalam klik kanan fungsionalitas Laporan Standar SQL Server. Untuk sampai ke laporan ini, navigasikan dari objek server di Object Explorer, pindah ke objek Database, lalu klik kanan database apa pun. Dari menu yang muncul, pilih Laporan, lalu Laporan Standar, dan kemudian "Disk Usage by Partition: [DatabaseName]".

Gandar
sumber
3
Ini rapi meskipun penggunaan sp_msforeachtableSSMS dengan mudah mungkin memicu System.OutOfMemoryExceptionjika Anda memiliki sejumlah besar tabel, jadi mungkin ide yang lebih baik untuk menggunakan tabel sementara untuk menyimpan hasilnya.
syneticon-dj
1
Masalah utama yang dapat saya lihat dengan sp_spacedused adalah tampaknya mengembalikan data dalam format yang dapat dibaca manusia (misalnya dalam kolom 'cadangan' dalam kasus saya yang memiliki '152 KB'). Saya menganggap ini akan beralih ke MB / GB yang sesuai. Ini jelas berguna dalam banyak situasi tetapi tidak jika Anda perlu menerapkan logika berdasarkan ukuran, atau ingin membandingkan nilai atau apa pun. Saya mencari cara untuk mematikan itu, tapi saya tidak bisa menemukan satu (saya menggunakan SQL Server 2005 :()
DarthPablo
55

Berikut adalah metode lain: menggunakan SQL Server Management Studio , di Object Explorer , buka database Anda dan pilih Tables

masukkan deskripsi gambar di sini

Kemudian buka Rincian Obyek Explorer (baik dengan menekan F7 atau pergi ke View-> Rincian Obyek Explorer ). Di halaman detail objek explorer, klik kanan pada header kolom dan aktifkan kolom yang ingin Anda lihat di halaman. Anda dapat mengurutkan data berdasarkan kolom apa pun juga.

masukkan deskripsi gambar di sini

Burung gereja
sumber
Ya, SSMS di Azure tidak memiliki beberapa fitur dibandingkan dengan versi lokal.
Sparrow
@batmaci Tidak yakin apakah ini berfungsi sama sekali saat Anda berkomentar tentang database Azure SQL, tetapi tampaknya setidaknya sebagian berfungsi sekarang di versi terbaru SSMS. Bagi saya sepertinya permintaan untuk tabel metadata adalah waktu habis, tetapi sebelum itu sepertinya mengembalikan beberapa (3-10) tabel nilai, termasuk (andal) tabel yang dipilih. Pilih tabel dan klik segarkan untuk melihat tabel yang Anda inginkan jika tidak ditampilkan.
pcdev
Azure bukan SQL Server "nyata" (ha ha)
Insinyur Terbalik
Saya menggunakan ini untuk Azure, terima kasih dengan (plus satu),
Irf
Anda juga dapat mengekspor daftar dalam file CSV dengan menggunakan utilitas seperti NirSoft SysExporter: nirsoft.net/utils/sysexp.html
Maks
39

Setelah beberapa pencarian, saya tidak dapat menemukan cara mudah untuk mendapatkan informasi tentang semua tabel. Ada prosedur tersimpan yang berguna bernama sp_spaceused yang akan mengembalikan semua ruang yang digunakan oleh database. Jika disediakan dengan nama tabel, itu mengembalikan ruang yang digunakan oleh tabel itu. Namun, hasil yang dikembalikan oleh prosedur tersimpan tidak dapat disortir, karena kolom adalah nilai karakter.

Script berikut akan menghasilkan informasi yang saya cari.

create table #TableSize (
    Name varchar(255),
    [rows] int,
    reserved varchar(255),
    data varchar(255),
    index_size varchar(255),
    unused varchar(255))
create table #ConvertedSizes (
    Name varchar(255),
    [rows] int,
    reservedKb int,
    dataKb int,
    reservedIndexSize int,
    reservedUnused int)

EXEC sp_MSforeachtable @command1="insert into #TableSize
EXEC sp_spaceused '?'"
insert into #ConvertedSizes (Name, [rows], reservedKb, dataKb, reservedIndexSize, reservedUnused)
select name, [rows], 
SUBSTRING(reserved, 0, LEN(reserved)-2), 
SUBSTRING(data, 0, LEN(data)-2), 
SUBSTRING(index_size, 0, LEN(index_size)-2), 
SUBSTRING(unused, 0, LEN(unused)-2)
from #TableSize

select * from #ConvertedSizes
order by reservedKb desc

drop table #TableSize
drop table #ConvertedSizes
Eric
sumber
Setelah melihat di atas menggunakan foreach dan SP akan menulis sesuatu seperti ini, senang saya menggulir ke bawah untuk melihatnya menghemat sedikit waktu.
Brad
37
 exec  sp_spaceused N'dbo.MyTable'

Untuk semua tabel, gunakan .. (menambahkan dari komentar Paul)

exec sp_MSForEachTable 'exec sp_spaceused [?]'
Royi Namir
sumber
5
Sneaky - Anda berubah dari exec sp_helpdbyang tidak menunjukkan apa-apa tentang tabel, ke exec sp_spaceusedyang tidak - tetapi hanya untuk satu tabel pada satu waktu ... itu tidak memberi Anda gambaran tentang tabel apa yang Anda miliki dan berapa banyak baris yang mereka miliki dan berapa banyak ruang yang mereka ambil.
marc_s
4
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Paul
27

Kueri di atas baik untuk menemukan jumlah ruang yang digunakan oleh tabel (termasuk indeks), tetapi jika Anda ingin membandingkan berapa banyak ruang yang digunakan oleh indeks di atas meja, gunakan kueri ini:

SELECT
    OBJECT_NAME(i.OBJECT_ID) AS TableName,
    i.name AS IndexName,
    i.index_id AS IndexID,
    8 * SUM(a.used_pages) AS 'Indexsize(KB)'
FROM
    sys.indexes AS i
    JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
    JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
WHERE
    i.is_primary_key = 0 -- fix for size discrepancy
GROUP BY
    i.OBJECT_ID,
    i.index_id,
    i.name
ORDER BY
    OBJECT_NAME(i.OBJECT_ID),
    i.index_id
Jens Frandsen
sumber
Apa alasan yang menyimpulkan kolom Indexsize (KB) untuk tabel tertentu tidak setuju dengan index_size dari sp_spaceused?
Derek
@ Derek Memperbaiki jawabannya dengan menambahkan where [i].[is_primary_key] = 0. Sekarang ukurannya harus sesuai.
CodeAngry
Terima kasih, tetapi ini sebenarnya juga tidak berhasil. Saya memiliki basis data uji (sangat kecil), tabel minat memiliki dua indeks - indeks utama berkerumun di satu kolom dan indeks non-berkerumun di dua kolom lainnya. Kueri ini mengatakan masing-masing menggunakan 16kB, tetapi sp_spaceused mengatakan total penggunaan indeks adalah 24kB. Bagian dari kebingungan saya adalah ini: Membandingkan pertanyaan ini dengan "UsedSpaceKB" dari jawaban yang diterima, saya tidak melihat perbedaan nyata. Gabungan yang sama, baru saja melewatkan penambahan sys.tables. Apakah saya melewatkan sesuatu, atau apakah permintaan ini secara inheren rusak?
Derek
Saya memiliki basis data besar. Dan ukuran cocok dengan sp_spaceused. Saya mengukur GB jadi beberapa MB tidak cocok tidak banyak. Saya tidak peduli tentang ukuran pasti, hanya sebuah ide.
CodeAngry
14

Jika Anda perlu menghitung angka yang persis sama, yang ada di halaman 'properti tabel - penyimpanan' di SSMS, Anda perlu menghitungnya dengan metode yang sama seperti yang dilakukan dalam SSMS (berfungsi untuk sql server 2005 dan di atas ... dan juga berfungsi dengan benar untuk tabel dengan bidang LOB - karena hanya menghitung "used_pages" tidak cukup untuk menunjukkan ukuran indeks yang akurat):

;with cte as (
SELECT
t.name as TableName,
SUM (s.used_page_count) as used_pages_count,
SUM (CASE
            WHEN (i.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) as pages
FROM sys.dm_db_partition_stats  AS s 
JOIN sys.tables AS t ON s.object_id = t.object_id
JOIN sys.indexes AS i ON i.[object_id] = t.[object_id] AND s.index_id = i.index_id
GROUP BY t.name
)
select
    cte.TableName, 
    cast((cte.pages * 8.)/1024 as decimal(10,3)) as TableSizeInMB, 
    cast(((CASE WHEN cte.used_pages_count > cte.pages 
                THEN cte.used_pages_count - cte.pages
                ELSE 0 
          END) * 8./1024) as decimal(10,3)) as IndexSizeInMB
from cte
order by 2 desc
sqladmin
sumber
14

Ekstensi ke @xav menjawab bahwa partisi tabel ditangani untuk mendapatkan ukuran dalam MB dan GB. Diuji pada SQL Server 2008/2012 (Mengomentari baris di mana is_memory_optimized = 1)

SELECT
    a2.name AS TableName,
    a1.rows as [RowCount],
    --(a1.reserved + ISNULL(a4.reserved,0)) * 8 AS ReservedSize_KB,
    --a1.data * 8 AS DataSize_KB,
    --(CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS IndexSize_KB,
    --(CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS UnusedSize_KB,
    CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_MB,
    CAST(ROUND(a1.data * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_MB,
    CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_MB,
    CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_MB,
    --'| |' Separator_MB_GB,
    CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_GB,
    CAST(ROUND(a1.data * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_GB,
    CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_GB,
    CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_GB
FROM
    (SELECT 
        ps.object_id,
        SUM (CASE WHEN (ps.index_id < 2) THEN row_count ELSE 0 END) AS [rows],
        SUM (ps.reserved_page_count) AS reserved,
        SUM (CASE
                WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
                ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
            END
            ) AS data,
        SUM (ps.used_page_count) AS used
    FROM sys.dm_db_partition_stats ps
        --===Remove the following comment for SQL Server 2014+
        --WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
    GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN 
    (SELECT 
        it.parent_id,
        SUM(ps.reserved_page_count) AS reserved,
        SUM(ps.used_page_count) AS used
     FROM sys.dm_db_partition_stats ps
     INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
     WHERE it.internal_type IN (202,204)
     GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id ) 
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
--AND a2.name = 'MyTable'       --Filter for specific table
--ORDER BY a3.name, a2.name
ORDER BY ReservedSize_MB DESC
Santhoshkumar KB
sumber
urutan juga lebih baik.
Pxtl
Ini harus menjadi jawaban teratas.
Baodad
14

Untuk Azure saya menggunakan ini:

Anda harus memiliki SSMS v17.x

Saya menggunakan;

masukkan deskripsi gambar di sini

Dengan ini, seperti yang disebutkan Sparrow Pengguna :

Buka Databases> Anda dan pilih Tables ,
Kemudian tekan tombol F7 Anda akan melihat row count
sebagai: masukkan deskripsi gambar di sini

SSMS di sini terhubung ke database Azure

Irf
sumber
3
F7 sangat jarang digunakan.
cskwg
1
Saya tidak tahu ini ada, saya agak malu pada diri sendiri: p Terima kasih!
lollancf37
Ini memiliki masalah dengan memori yang dioptimalkan tabel, (saya baru diuji setelah melihat posting ini :)
Amirreza
11

Kami menggunakan tabel partisi dan mengalami beberapa masalah dengan kueri yang disediakan di atas karena rekaman duplikat.

Bagi mereka yang membutuhkan ini, Anda dapat menemukan kueri di bawah ini yang dijalankan oleh SQL Server 2014 saat membuat laporan "Disk use by table". Saya menganggap itu juga berfungsi dengan versi SQL Server sebelumnya.

Itu bekerja seperti pesona.

SELECT
    a2.name AS [tablename],
    a1.rows as row_count,
    (a1.reserved + ISNULL(a4.reserved,0))* 8 AS reserved, 
    a1.data * 8 AS data,
    (CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS index_size,
    (CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS unused
FROM
    (SELECT 
        ps.object_id,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN row_count
                ELSE 0
            END
            ) AS [rows],
        SUM (ps.reserved_page_count) AS reserved,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
                ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
            END
            ) AS data,
        SUM (ps.used_page_count) AS used
    FROM sys.dm_db_partition_stats ps
        WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
    GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN 
    (SELECT 
        it.parent_id,
        SUM(ps.reserved_page_count) AS reserved,
        SUM(ps.used_page_count) AS used
     FROM sys.dm_db_partition_stats ps
     INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
     WHERE it.internal_type IN (202,204)
     GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id ) 
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
ORDER BY a3.name, a2.name
xav
sumber
Terima kasih untuk skrip yang cocok dengan SSMS melakukannya, dan menangani partisi dengan benar.
Mike
8
-- Show the size of all the tables in a database sort by data size descending
SET NOCOUNT ON
DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
DECLARE @cmd1 varchar(500)
SET @cmd1 = 'exec sp_spaceused ''?'''

INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
EXEC sp_msforeachtable @command1=@cmd1

SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
Menandai
sumber
8

Perubahan kecil pada jawaban Mar_c , karena saya telah sering kembali ke halaman ini, dipesan oleh sebagian besar baris pertama:

SELECT
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB,
    SUM(a.used_pages) * 8 AS UsedSpaceKB,
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
LEFT OUTER JOIN
    sys.schemas s ON t.schema_id = s.schema_id
WHERE
    t.NAME NOT LIKE 'dt%'
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255
GROUP BY
    t.Name, s.Name, p.Rows
ORDER BY
    --p.rows DESC --Uncomment to order by amount rows instead of size in KB.
    SUM(a.total_pages) DESC 
Joel Harkes
sumber
5

Ini akan memberi Anda ukuran, dan mencatat jumlah untuk setiap tabel.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- Get a list of tables and their sizes on disk
ALTER PROCEDURE [dbo].[sp_Table_Sizes]
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
DECLARE @table_name VARCHAR(500)  
DECLARE @schema_name VARCHAR(500)  
DECLARE @tab1 TABLE( 
        tablename VARCHAR (500) collate database_default 
       ,schemaname VARCHAR(500) collate database_default 
) 

CREATE TABLE #temp_Table ( 
        tablename sysname 
       ,row_count INT 
       ,reserved VARCHAR(50) collate database_default 
       ,data VARCHAR(50) collate database_default 
       ,index_size VARCHAR(50) collate database_default 
       ,unused VARCHAR(50) collate database_default  
) 

INSERT INTO @tab1  
SELECT Table_Name, Table_Schema  
FROM information_schema.tables  
WHERE TABLE_TYPE = 'BASE TABLE' 

DECLARE c1 CURSOR FOR 
SELECT Table_Schema + '.' + Table_Name   
FROM information_schema.tables t1  
WHERE TABLE_TYPE = 'BASE TABLE' 

OPEN c1 
FETCH NEXT FROM c1 INTO @table_name 
WHILE @@FETCH_STATUS = 0  
BEGIN   
        SET @table_name = REPLACE(@table_name, '[','');  
        SET @table_name = REPLACE(@table_name, ']','');  

        -- make sure the object exists before calling sp_spacedused 
        IF EXISTS(SELECT id FROM sysobjects WHERE id = OBJECT_ID(@table_name)) 
        BEGIN 
               INSERT INTO #temp_Table EXEC sp_spaceused @table_name, false; 
        END 

        FETCH NEXT FROM c1 INTO @table_name 
END 
CLOSE c1 
DEALLOCATE c1 

SELECT  t1.* 
       ,t2.schemaname  
FROM #temp_Table t1  
INNER JOIN @tab1 t2 ON (t1.tablename = t2.tablename ) 
ORDER BY schemaname,t1.tablename; 

DROP TABLE #temp_Table
END
William Walseth
sumber
2
Jika Anda memposting kode, XML, atau sampel data, TOLONG soroti baris tersebut di editor teks dan klik tombol "kode sampel" ( { }) pada bilah alat editor untuk memformat dan sintaksis dengan baik!
marc_s
4

Untuk mendapatkan semua ukuran tabel dalam satu database Anda dapat menggunakan kueri ini:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

Dan Anda dapat mengubahnya untuk memasukkan semua hasil ke tabel temp dan setelah itu pilih dari tabel temp.

Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" ' 
Select * from #TempTable
Ardalan Shahgholi
sumber
3

Dari prompt perintah menggunakan OSQL :

OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt
pengguna4658783
sumber
3

Berikut adalah cara untuk mendapatkan ukuran semua tabel dengan cepat dengan langkah-langkah berikut:

  1. Tulis perintah T-SQL yang diberikan untuk mendaftar semua tabel database:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. Sekarang salin daftar tabel database, dan salin ke jendela penganalisa permintaan baru

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. Dalam penganalisis kueri SQL , pilih dari bilah alat pilihan hasil atas ke file ( Ctrl+ Shift+ F).

  4. Sekarang akhirnya tekan tombol Execute yang ditandai merah dari bilah alat di atas .

  5. Ukuran database semua tabel sekarang disimpan dalam file di komputer Anda.

    Masukkan deskripsi gambar di sini

Anjan Kant
sumber
2

Saya menambahkan beberapa kolom di atas jawaban marc_s:

with fs
as
(
select i.object_id,
        p.rows AS RowCounts,
        SUM(a.total_pages) * 8 AS TotalSpaceKb
from     sys.indexes i 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 
    i.OBJECT_ID > 255 
GROUP BY 
    i.object_id,
    p.rows
)

SELECT 
    t.NAME AS TableName,
    fs.RowCounts,
    fs.TotalSpaceKb,
    t.create_date,
    t.modify_date,
    ( select COUNT(1)
        from sys.columns c 
        where c.object_id = t.object_id ) TotalColumns    
FROM 
    sys.tables t INNER JOIN      
    fs  ON t.OBJECT_ID = fs.object_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
ORDER BY 
    t.Name
Alan Cardoso
sumber
1

Posting saya hanya relevan untuk SQL Server 2000 dan telah diuji untuk berfungsi di lingkungan saya.

Kode ini mengakses Semua database yang mungkin dari sebuah instance , bukan hanya satu database.

Saya menggunakan dua tabel temp untuk membantu mengumpulkan data yang sesuai dan kemudian membuang hasilnya ke satu tabel 'Langsung'.

Data yang dikembalikan adalah: DatabaseName, DatabaseTableName, Baris (dalam Tabel), data (ukuran tabel dalam KB tampaknya), entri data (saya menemukan ini berguna untuk mengetahui kapan terakhir kali saya menjalankan skrip).

Downfall ke kode ini adalah bidang 'data' tidak disimpan sebagai int (Karakter 'KB' disimpan di bidang itu), dan itu akan berguna (tetapi tidak sepenuhnya diperlukan) untuk menyortir.

Semoga kode ini membantu seseorang di luar sana dan menghemat waktu mereka!

CREATE PROCEDURE [dbo].[usp_getAllDBTableSizes]

AS
BEGIN
   SET NOCOUNT OFF

   CREATE TABLE #DatabaseTables([dbname] sysname,TableName sysname)
   CREATE TABLE #AllDatabaseTableSizes(Name sysname,[rows] VARCHAR(18), reserved VARCHAR(18), data VARCHAR(18), index_size VARCHAR(18), unused VARCHAR(18))

   DECLARE @SQL nvarchar(4000)
   SET @SQL='select ''?'' AS [Database], Table_Name from [?].information_schema.tables WHERE TABLE_TYPE = ''BASE TABLE'' '

   INSERT INTO #DatabaseTables(DbName, TableName)
      EXECUTE sp_msforeachdb @Command1=@SQL

   DECLARE AllDatabaseTables CURSOR LOCAL READ_ONLY FOR   
   SELECT TableName FROM #DatabaseTables

   DECLARE AllDatabaseNames CURSOR LOCAL READ_ONLY FOR   
   SELECT DBName FROM #DatabaseTables

   DECLARE @DBName sysname  
   OPEN AllDatabaseNames  

   DECLARE @TName sysname
   OPEN AllDatabaseTables  

   WHILE 1=1 BEGIN 
      FETCH NEXT FROM AllDatabaseNames INTO @DBName  
      FETCH NEXT FROM AllDatabaseTables INTO @TName 
      IF @@FETCH_STATUS<>0 BREAK  
      INSERT INTO #AllDatabaseTableSizes
         EXEC ( 'EXEC ' + @DBName + '.dbo.sp_spaceused ' + @TName) 

   END 

   --http://msdn.microsoft.com/en-us/library/aa175920(v=sql.80).aspx
   INSERT INTO rsp_DatabaseTableSizes (DatabaseName, name, [rows], data)
      SELECT   [dbname], name, [rows],  data FROM #DatabaseTables
      INNER JOIN #AllDatabaseTableSizes
      ON #DatabaseTables.TableName = #AllDatabaseTableSizes.Name
      GROUP BY [dbname] , name, [rows],  data
      ORDER BY [dbname]
   --To be honest, I have no idea what exact duplicates we are dropping
    -- but in my case a near enough approach has been good enough.
   DELETE FROM [rsp_DatabaseTableSizes]
   WHERE name IN 
      ( 
      SELECT name 
      FROM [rsp_DatabaseTableSizes]
      GROUP BY name
      HAVING COUNT(*) > 1
      )

   DROP TABLE #DatabaseTables
   DROP TABLE #AllDatabaseTableSizes

   CLOSE AllDatabaseTables  
   DEALLOCATE AllDatabaseTables  

   CLOSE AllDatabaseNames  
   DEALLOCATE AllDatabaseNames      
END

--EXEC [dbo].[usp_getAllDBTableSizes] 

Jika Anda perlu tahu, tabel rsp_DatabaseTableSizes dibuat melalui:

CREATE TABLE [dbo].[rsp_DatabaseSizes](
    [DatabaseName] [varchar](1000) NULL,
    [dbSize] [decimal](15, 2) NULL,
    [DateUpdated] [smalldatetime] NULL
) ON [PRIMARY]

GO
Andrew
sumber
1

Sebagai ekstensi sederhana untuk jawaban marc_s (yang telah diterima), ini disesuaikan untuk mengembalikan jumlah kolom dan memungkinkan pemfilteran:

SELECT *
FROM
(

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    COUNT(DISTINCT c.COLUMN_NAME) as ColumnCount,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    (SUM(a.used_pages) * 8) AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
INNER JOIN
    INFORMATION_SCHEMA.COLUMNS c ON t.NAME = c.TABLE_NAME
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255
GROUP BY 
    t.Name, s.Name, p.Rows
) AS Result

WHERE
    RowCounts > 1000
    AND ColumnCount > 10
ORDER BY 
    UsedSpaceKB DESC
Zach Smith
sumber
Setelah Anda bergabung dengan tabel kolom, Anda tidak lagi memiliki ruang tabel yang tepat. Bagian luar akan diperbaiki.
dreamca4er
0

Riffing pada @Mark jawaban di atas, menambahkan @ updateusage = 'true' untuk memaksa statistik ukuran terbaru ( https://msdn.microsoft.com/en-us/library/ms188776.aspx ):

        SET NOCOUNT ON
        DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
        DECLARE @cmd1 varchar(500)
        SET @cmd1 = 'exec sp_spaceused @objname =''?'', @updateusage =''true'' '

        INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
        EXEC sp_msforeachtable @command1=@cmd1 
SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
Chris Smith
sumber
0

Berikut adalah contoh permintaan untuk mendapatkan tabel yang lebih besar dari 1GB yang dipesan berdasarkan ukuran menurun.

USE YourDB
GO

DECLARE @Mult float = 8
SET @Mult = @Mult / POWER(2, 20) -- Use POWER(2, 10) for MBs

; WITH CTE AS
(
SELECT
    i.object_id,
    Rows = MAX(p.rows),
    TotalSpaceGB = ROUND(SUM(a.total_pages) * @Mult, 0),
    UsedSpaceGB = ROUND(SUM(a.used_pages) * @Mult, 0)
FROM 
    sys.indexes i
JOIN
    sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN
    sys.allocation_units a ON p.partition_id = a.container_id
WHERE
    i.object_id > 255
GROUP BY
    i.object_id
HAVING
    SUM(a.total_pages) * @Mult > 1
)
SELECT 
    SchemaName = s.name,
    TableName = t.name,
    c.TotalSpaceGB,
    c.UsedSpaceGB,
    UnusedSpaceGB = c.TotalSpaceGB - c.UsedSpaceGB,
    [RowCount] = c.Rows
FROM 
    CTE c
JOIN    
    sys.tables t ON t.object_id = c.object_id
JOIN
    sys.schemas s ON t.schema_id = s.schema_id
ORDER BY
    c.TotalSpaceGB DESC
Sergey
sumber