Come si può sapere quali tabelle occupano più spazio in un database di SQL Server 2005?


90

Come si può sapere quali tabelle occupano più spazio in un database di SQL Server 2005?

Sono sicuro che ci sia una procedura memorizzata di sistema che mostra queste informazioni.

Ho un database di TEST che è cresciuto da 1 tb a 23 tb. Attualmente stiamo eseguendo molti test di conversione del client nel database, il che comporta l'esecuzione della stessa stored procedure di conversione più volte. Fa CANCELLA che sono sicuro sta aumentando il registro delle transazioni. Ma questo mi ha fatto pensare di porre questa domanda.

Informazioni

il grosso problema è la tabella dbo.Download, crea un enorme spazio di archiviazione che in realtà non è necessario, avevo 3 GB prima di troncarlo, quindi 52 MB;)


2
Le risposte di Marc_S e Barry erano semplicemente eccezionali, quindi ho votato entrambi e stavo aspettando di vedere quale ha ottenuto il maggior numero di voti in modo da poterlo ricompensare con la "Risposta accettata". Ma erano entrambi in parità a 5, quindi ne ho scelto uno ma li ho usati entrambi. Grazie mille Marc_S e Barry!
Gerhard Weiss

Risposte:


208

Prova questo script: elencherà il numero di righe e lo spazio utilizzato dalle righe di dati (e lo spazio totale utilizzato) per tutte le tabelle nel database:

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) 

6
+1 brillante. Nota che questo non include la dimensione degli indici di dati. Per me, però, ha fatto il suo lavoro.
Erick Robertson

39
Non lo sapevo, ma se utilizzi Management Studio puoi anche fare clic con il pulsante destro del mouse sul database e andare su Rapporti -> Utilizzo del disco per tabella per gli stessi risultati.
rossisdead

@rossisdead, è un'informazione esilarante da sapere. Grazie!
Nickmaovich

Ottengo "Tabella" sys.tables "non esiste"
Seano

@Seano: quale versione di SQL Server stai utilizzando? (corri SELECT @@VERSIONper scoprirlo) Quale livello di compatibilità del database ha il tuo database ??
marc_s

33

Usa sp_spacedUsed

Exec sp_spaceused N'YourTableName'

O se vuoi eseguire il sp_spaceusedper ogni tabella nel tuo database, puoi usare questo SQL:

set nocount on
create table #spaceused (
  name nvarchar(120),
  rows char(11),
  reserved varchar(18),
  data varchar(18),
  index_size varchar(18),
  unused varchar(18)
)

declare Tables cursor for
  select name
  from sysobjects where type='U'
  order by name asc

OPEN Tables
DECLARE @table varchar(128)

FETCH NEXT FROM Tables INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN
  insert into #spaceused exec sp_spaceused @table
  FETCH NEXT FROM Tables INTO @table
END

CLOSE Tables
DEALLOCATE Tables 

select * from #spaceused
drop table #spaceused

exec sp_spaceused

L'SQL sopra viene da qui


7
Per le versioni più recenti di SQL Server puoi anche usareexec sp_msforeachtable 'exec sp_spaceused N''?'''
JNK

1
@JNK sp_msforeachtableesiste almeno da SQl Server 2000
SQLMenace

@SQLMenace - grazie per le informazioni. Non ho ricercato quanti anni avesse prima di pubblicare, ma non ero sicuro di trovarlo poiché non è documentato.
JNK

4
Un esempio leggermente più semplice: puoi farla franca saltando gli EXEC e citando fantasia, facendo solo sp_msforeachtable 'sp_spaceused [?]'se lo desideri. Verificato di nuovo a SQL2000.
Mark

Segna il problema con questo metodo è che non restituisce un singolo set di risultati
Paul

7

Il commento di Rossisdead ha risposto al meglio a questa domanda per me, vorrei che non fosse sepolto in un commento. Questo sarà utile per le persone come me che non cercano di scrivere la soluzione (l'OP non ha chiesto uno snippet di codice)

Se stai utilizzando Management Studio, puoi anche fare clic con il pulsante destro del mouse sul database e andare su Rapporti -> Utilizzo del disco per tabella per gli stessi risultati


Per enfasi: fare clic con il pulsante destro del mouse sul database e non
sull'istanza

4

Grazie a @marc_s per la risposta. Avevo bisogno di conoscere i dati rispetto allo spazio dell'indice, quindi sono andato avanti e ho ampliato la query per includerlo.

SELECT TableName
    , SUM(DataRowCounts) AS DataRowCounts
    , SUM(DataTotalSpaceGB) AS DataTotalSpaceGB
    , SUM(DataSpaceUsedGB) AS DataSpaceUsedGB
    , SUM(DataUnusedSpaceGB) AS DataUnusedSpaceGB
    , SUM(IndexRowCounts) AS IndexRowCounts
    , SUM(IndexTotalSpaceGB) AS IndexTotalSpaceGB
    , SUM(IndexSpaceUsedGB) AS IndexSpaceUsedGB
    , SUM(IndexUnusedSpaceGB) AS IndexUnusedSpaceGB
    , SUM(DataTotalSpaceGB) + SUM(IndexTotalSpaceGB) AS TotalSpaceGB
FROM
(
SELECT t.NAME AS TableName
    , i.type_desc AS IndexType
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataTotalSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS DataSpaceUsedGB    
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataUnusedSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN SUM(p.Rows) ELSE 0 END AS DataRowCounts
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexTotalSpaceGB
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS IndexSpaceUsedGB    
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexUnusedSpaceGB  
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN SUM(p.Rows) ELSE 0 END AS IndexRowCounts
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 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
    AND s.Name = 'dbo' --update this filter
    AND t.Name = 'MyTable'
GROUP BY t.Name
    , i.type_desc
) x
GROUP BY TableName
ORDER BY 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.