Ottieni le dimensioni di tutte le tabelle nel database


1271

Ho ereditato un database SQL Server abbastanza grande. Sembra occupare più spazio di quanto mi aspetterei, dati i dati che contiene.

C'è un modo semplice per determinare la quantità di spazio su disco che ogni tabella sta consumando?


a quali ruoli hai accesso? Sei il DBA o è gestito tramite un host web, un client o simili?
Rob Allen,

possibile duplicato della dimensione
Joe Stefanelli,

@RobAllen Ho pieno accesso al database, quindi uno script che richiede qualsiasi ruolo è sufficiente.
Eric,


Per Azure Ho usato questo
Irf

Risposte:


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

7
Domanda sciocca, ma è possibile che questa query possa causare il blocco delle righe?
GEMI

7
Anche gli indici utilizzano lo spazio e la quantità di spazio utilizzata dagli indici può essere trovata con questa query di seguito.
Jens Frandsen,

6
Lo script ha problemi con gli indici filtrati: per ogni indice filtrato per una determinata tabella, vedo una riga aggiuntiva con il nome di quella tabella nei risultati. I "RowCounts" di ciascuna di quelle righe extra corrispondono al numero di righe coperte da uno degli indici filtrati. (su Mq2012)
Akos Lukacs

37
@Todd: alcune persone vogliono ordinato in questo modo - gli altri vogliono da nome della tabella - fate la vostra scelta, adattare il codice in base alle esigenze ....
marc_s

12
Se le tue tabelle sono partizionate, vengono visualizzate più volte senza alcuna indicazione di ciò che sta succedendo. È possibile aggiungere p.partition_number all'elenco di selezione oppure SUM (p.Rows) e rimuoverlo dal gruppo tramite.
PRMan,

561

Se si utilizza SQL Server Management Studio (SSMS), anziché eseguire una query ( che nel mio caso ha restituito righe duplicate ) è possibile eseguire un report standard

  1. Fare clic con il tasto destro sul database
  2. Passare a Rapporti> Rapporti standard> Utilizzo del disco per tabella

Nota: il livello di compatibilità del database deve essere impostato su 90 o superiore affinché funzioni correttamente. Vedi http://msdn.microsoft.com/en-gb/library/bb510680.aspx


54
In Management Studio 2012 è possibile eseguire: Visualizza dettagli Esplora oggetti (F7) e passare a "Tabelle" in Esplora oggetti. In Dettagli fai clic con il pulsante destro del mouse sull'intestazione e seleziona le colonne delle dimensioni.
ValGe

3
per consigliare nuove funzionalità con SSMS 2012. Per noi vecchi geezer, non abbiamo mai avuto questo a disposizione. Quindi l'abbiamo fatto alla vecchia maniera di TSQL :)
GoldBishop il

3
Che ci crediate o no, a volte i semplici mortali (sviluppatori) vorrebbero vedere queste informazioni e non abbiamo i permessi per usare il report integrato ma possiamo eseguire il TSQL nella risposta accettata. :) Cordiali saluti (A proposito, ho ancora votato a favore della tua risposta)
Andrew Steitz,

8
Non sembra essere presente in Azure SQL :-(
Simon_Weaver

1
So che non è grave, ma, per favore, spingi via i gruppi emarginati dall'ingegneria e dalla tecnologia con questa linea di ragionamento che si ripete ovunque. Dovresti imparare entrambe le cose, ma non dovresti castigare le persone per l'utilizzo di programmi di utilità per risparmiare tempo per lavorare in modo più intelligente e veloce. (Anche se SSMS sembra essere un "rallentamento dell'utilità" a volte ...: X) Personalmente le letture per i dati tabulari sono generalmente più chiare in una GUI, sebbene gli strumenti costruiti da Microsoft tendano ad essere le eccezioni per tutto ciò che riguarda l'UI.
Julia McGuigan,

102

sp_spaceused può ottenere informazioni sullo spazio su disco utilizzato da una tabella, una vista indicizzata o l'intero database.

Per esempio:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

Ciò riporta le informazioni sull'utilizzo del disco per la tabella ContactInfo.

Per usarlo per tutte le tabelle contemporaneamente:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

È inoltre possibile ottenere l'utilizzo del disco dalla funzionalità Report standard di SQL Server con il pulsante destro del mouse. Per accedere a questo rapporto, spostarsi dall'oggetto server in Esplora oggetti, spostarsi verso il basso sull'oggetto Database, quindi fare clic con il pulsante destro del mouse su qualsiasi database. Dal menu visualizzato, selezionare Rapporti, quindi Rapporti standard, quindi "Utilizzo disco per partizione: [Nome database]".


3
Ciò è corretto, sebbene l'uso di sp_msforeachtableSSMS possa facilmente innescare a System.OutOfMemoryExceptionse si dispone di un numero elevato di tabelle, quindi potrebbe essere una buona idea utilizzare una tabella temporanea per archiviare i risultati.
syneticon-dj,

1
Il problema principale che posso vedere con sp_spacedused è che sembra restituire i dati in un formato leggibile dall'uomo (ad esempio nella colonna "riservato" nel mio caso aveva "152 KB"). Presumo che questo passerà a MB / GB come appropriato. Ciò è chiaramente utile in molte situazioni, ma non se è necessario applicare una logica basata sulla dimensione o se si desidera confrontare valori o altro. Ho cercato un modo per disattivarlo, ma non riuscivo a individuarne uno (sto usando SQL Server 2005 :()
DarthPablo

55

Ecco un altro metodo: utilizzando SQL Server Management Studio , in Esplora oggetti , vai al tuo database e seleziona Tabelle

inserisci qui la descrizione dell'immagine

Quindi aprire i dettagli di Esplora oggetti (premendo F7 o andando su Visualizza-> Dettagli di Esplora oggetti ). Nella pagina dei dettagli di Esplora oggetti, fai clic con il pulsante destro del mouse sull'intestazione della colonna e abilita le colonne che desideri visualizzare nella pagina. Puoi ordinare i dati anche per qualsiasi colonna.

inserisci qui la descrizione dell'immagine


Sì, SSMS in Azure manca di alcune funzionalità rispetto alla versione locale.
Sparrow

@batmaci Non sono sicuro che funzionasse quando hai commentato i database SQL di Azure, ma ora sembra funzionare almeno in parte nelle recenti versioni di SSMS. Per me sembra che la query per i metadati della tabella stia scadendo, ma prima sembra restituire un valore di alcune (3-10) tabelle, inclusa (in modo affidabile) la tabella selezionata. Seleziona una tabella e fai clic su Aggiorna per vedere la tabella desiderata se non viene visualizzata.
pcdev,

Azure non è "vero" SQL Server (ah ah)
Reversed Engineer,

Ho usato questo per Azure, grazie a un (più uno),
Irf

È inoltre possibile esportare l'elenco in un file CSV utilizzando un'utilità come NirSoft SysExporter: nirsoft.net/utils/sysexp.html
Max

39

Dopo alcune ricerche, non sono riuscito a trovare un modo semplice per ottenere informazioni su tutte le tabelle. Esiste una pratica procedura memorizzata denominata sp_spaceused che restituirà tutto lo spazio utilizzato dal database. Se fornito con un nome di tabella, restituisce lo spazio utilizzato da quella tabella. Tuttavia, i risultati restituiti dalla procedura memorizzata non sono ordinabili, poiché le colonne sono valori di carattere.

Il seguente script genererà le informazioni che sto cercando.

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

Dopo aver visto quanto sopra usando foreach e SP avrebbe scritto qualcosa del genere, sono contento di averlo fatto scorrere verso il basso per vedere che mi ha fatto risparmiare un po 'di tempo.
Brad

37
 exec  sp_spaceused N'dbo.MyTable'

Per tutte le tabelle, utilizzare .. (aggiunta dai commenti di Paul)

exec sp_MSForEachTable 'exec sp_spaceused [?]'

5
Subdolo - sei cambiato da exec sp_helpdbquale non mostra nulla sulle tabelle, a exec sp_spaceusedcui lo fa - ma solo per una tabella alla volta ... non ti dà una panoramica di quali tabelle hai e quante righe hanno e come molto spazio occupano.
marc_s,

4
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Paul

27

Le query precedenti sono utili per trovare la quantità di spazio utilizzata dalla tabella (indici inclusi), ma se si desidera confrontare la quantità di spazio utilizzata dagli indici sulla tabella, utilizzare questa query:

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

Qual è il motivo per cui il riepilogo della colonna Indexsize (KB) per una determinata tabella non è d'accordo con index_size di sp_spaceused?
Derek,

@Derek Risolto il problema con la sua aggiunta where [i].[is_primary_key] = 0. Ora le dimensioni dovrebbero corrispondere.
CodeAngry

Grazie, ma in realtà neanche questo funziona. Ho un database di test (molto piccolo), la tabella di interesse ha due indici: un indice cluster primario su una colonna e un indice non cluster su due delle altre colonne. Questa query indica che ciascuno di essi utilizza 16 KB, ma sp_spaceused indica che l'utilizzo totale dell'indice è di 24 kB. Parte della mia confusione è questa: confrontando questa query con "UsedSpaceKB" della risposta accettata, non vedo una vera differenza. Stessi join, manca solo l'aggiunta di sys.tables. Mi sto perdendo qualcosa o questa query è intrinsecamente rotta?
Derek,

Ho database di grandi dimensioni. E le dimensioni corrispondono a sp_spaceused. Misuro i GB, quindi alcuni mega non corrispondenti non sono molti. Non mi importa delle dimensioni esatte, solo un'idea.
CodeAngry

14

Se è necessario calcolare esattamente gli stessi numeri, che si trovano nella pagina "Proprietà tabella - archiviazione" in SSMS, è necessario contarli con lo stesso metodo utilizzato in SSMS (funziona per SQL Server 2005 e versioni successive ... e anche funziona correttamente per le tabelle con campi LOB - perché il solo conteggio di "pagine_utilizzate" non è sufficiente per mostrare una dimensione dell'indice accurata):

;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

14

L'estensione a @xav risponde alla gestione delle partizioni della tabella per ottenere dimensioni in MB e GB. Testato su SQL Server 2008/2012 (commentato una riga in cui 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

anche un migliore ordinamento.
Pxtl,

Questa dovrebbe essere la risposta migliore.
Baodad,

14

Per Azure ho usato questo:

Dovresti avere SSMS v17.x

Ero solito;

inserisci qui la descrizione dell'immagine

Con questo, come ha menzionato User Sparrow :

Apri Databases> e seleziona Tabelle ,
quindi premi il tasto F7 Dovresti vedere row count
come: inserisci qui la descrizione dell'immagine

Qui SSMS è connesso ai database di Azure


3
F7 è fortemente sottoutilizzato.
cskwg,

1
Non avevo idea che questo esistesse, mi vergogno un po 'di me stesso: p Grazie!
lollancf37,

Ha un problema con le tabelle ottimizzate per la memoria, (ho appena provato dopo aver visto questo post :)
Amirreza,

11

Usiamo il partizionamento delle tabelle e abbiamo avuto qualche problema con le query fornite sopra a causa di record duplicati.

Per coloro che ne hanno bisogno, è possibile trovare di seguito la query eseguita da SQL Server 2014 durante la generazione del report "Utilizzo del disco per tabella". Presumo che funzioni anche con le versioni precedenti di SQL Server.

Esso funziona magicamente.

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

Grazie per uno script che corrisponde a come lo fa SSMS e gestisce correttamente le partizioni.
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

8

Una piccola modifica alla risposta di Mar_c , da quando torno spesso a questa pagina, ordinata per la maggior parte delle prime righe:

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 

5

Questo ti darà le dimensioni e conta record per ogni tabella.

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

2
Se pubblichi esempi di codice, XML o dati, PER FAVORE evidenzia quelle righe nell'editor di testo e fai clic sul pulsante "esempi di codice" ( { }) sulla barra degli strumenti dell'editor per formattarlo e sintetizzarlo bene evidenziandolo!
marc_s,

4

Per ottenere tutte le dimensioni della tabella in un database è possibile utilizzare questa query:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

E puoi cambiarlo per inserire tutti i risultati nella tabella temporanea e successivamente selezionare dalla tabella temporanea.

Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" ' 
Select * from #TempTable

3

Da un prompt dei comandi utilizzando OSQL :

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

3

Ecco un modo per ottenere rapidamente tutte le dimensioni delle tabelle con i seguenti passaggi:

  1. Scrivi i comandi T-SQL forniti per elencare tutte le tabelle del database:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. Ora copia l'elenco delle tabelle del database e copialo in una nuova finestra dell'analizzatore di query

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. Nell'analizzatore di query SQL , selezionare dalla barra degli strumenti superiore l'opzione Risultati su file ( Ctrl+ Shift+ F).

  4. Ora finalmente premi il pulsante Esegui contrassegnato in rosso dalla barra degli strumenti sopra .

  5. La dimensione del database di tutte le tabelle è ora memorizzata in un file sul tuo computer.

    Inserisci qui la descrizione dell'immagine


2

Ho aggiunto qualche colonna in più sulla risposta di 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

1

Il mio post è rilevante solo per SQL Server 2000 ed è stato testato per funzionare nel mio ambiente.

Questo codice accede a tutti i possibili database di una singola istanza , non solo a un singolo database.

Uso due tabelle temporanee per aiutare a raccogliere i dati appropriati e quindi scaricare i risultati in una tabella "In diretta".

I dati restituiti sono: DatabaseName, DatabaseTableName, Righe (nella tabella), dati (sembrerebbe la dimensione della tabella in KB), dati di immissione (lo trovo utile per sapere quando ho eseguito l'ultima volta lo script).

L'errore di questo codice è che il campo "dati" non è memorizzato come int (i caratteri "KB" sono conservati in quel campo) e ciò sarebbe utile (ma non del tutto necessario) per l'ordinamento.

Spero che questo codice aiuti qualcuno là fuori e li risparmi un po 'di tempo!

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] 

Nel caso sia necessario sapere, la tabella rsp_DatabaseTableSizes è stata creata tramite:

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

GO

1

Come semplice estensione della risposta di marc_s (quella che è stata accettata), viene adattata per restituire il conteggio delle colonne e consentire il filtro:

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

Dopo aver aderito alla tabella Columns, non hai più il tablespace giusto. L'applicazione esterna sarà la correzione.
dreamca4er,

0

Riffing sulla risposta @Mark sopra, ha aggiunto @ updateusage = 'true' per forzare le ultime statistiche sulle dimensioni ( 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

0

Ecco una query di esempio per ottenere tabelle più grandi di 1 GB ordinate per dimensione decrescente.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.