Ruft die Größe aller Tabellen in der Datenbank ab


1271

Ich habe eine ziemlich große SQL Server-Datenbank geerbt. Angesichts der darin enthaltenen Daten scheint es mehr Platz in Anspruch zu nehmen, als ich erwarten würde.

Gibt es eine einfache Möglichkeit, um festzustellen, wie viel Speicherplatz jede Tabelle auf der Festplatte belegt?


Auf welche Rollen haben Sie Zugriff? Sind Sie der DBA oder wird dies über einen Webhost, einen Client oder ähnliches verwaltet?
Rob Allen


@RobAllen Ich habe vollen Zugriff auf die Datenbank, daher ist ein Skript, das eine Rolle erfordert, ausreichend.
Eric


Für Azure habe ich dies verwendet
Irf

Antworten:


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
Dumme Frage, aber ist es möglich, dass diese Abfrage eine Zeilensperrung verursachen kann?
GEMI

7
Indizes verwenden ebenfalls Speicherplatz, und der von Indizes verwendete Speicherplatz kann mit dieser Abfrage unten ermittelt werden.
Jens Frandsen

6
Ihr Skript hat Probleme mit gefilterten Indizes: Für jeden gefilterten Index für eine bestimmte Tabelle wird in den Ergebnissen eine zusätzliche Zeile mit dem Namen dieser Tabelle angezeigt. Die "RowCounts" jeder dieser zusätzlichen Zeilen entsprechen der Anzahl der Zeilen, die von einem der gefilterten Indizes abgedeckt werden. (am Sql2012)
Akos Lukacs

37
@Todd: Einige Leute wollen, dass es so bestellt wird - andere wollen es nach Tabellennamen - treffen Sie Ihre Wahl, passen Sie den Code nach Bedarf an ....
marc_s

12
Wenn Ihre Tabellen partitioniert sind, werden sie mehrmals angezeigt, ohne dass angegeben wird, was gerade passiert. Sie können entweder p.partition_number zur Auswahlliste hinzufügen oder SUM (p.Rows) und aus der Gruppe entfernen.
PRMan

561

Wenn Sie SQL Server Management Studio (SSMS) verwenden, können Sie anstelle einer Abfrage ( die in meinem Fall doppelte Zeilen zurückgibt) einen Standardbericht ausführen . 

  1. Klicken Sie mit der rechten Maustaste auf die Datenbank
  2. Navigieren Sie zu Berichte> Standardberichte> Datenträgerverwendung nach Tabelle

Hinweis: Die Datenbankkompatibilitätsstufe muss auf 90 oder höher eingestellt sein, damit dies ordnungsgemäß funktioniert. Siehe http://msdn.microsoft.com/en-gb/library/bb510680.aspx


54
In Management Studio 2012 können Sie: Objekt-Explorer-Details anzeigen (F7) und im Objekt-Explorer zu "Tabellen" navigieren. Klicken Sie unter Details mit der rechten Maustaste auf die Überschrift und wählen Sie Größenspalten aus.
ValGe

3
für die Beratung neuer Funktionen mit SSMS 2012. Für uns alte Leute hatten wir diese nie zur Verfügung. Also haben wir es einfach auf die alte TSQL-Art gemacht :)
GoldBishop

3
Ob Sie es glauben oder nicht, manchmal möchten nur Sterbliche (Entwickler) diese Informationen sehen, und wir haben keine Berechtigung, den integrierten Bericht zu verwenden, aber wir können die TSQL in der akzeptierten Antwort ausführen. :) FYI (Übrigens, ich habe Ihre Antwort immer noch positiv bewertet)
Andrew Steitz

8
Scheint in Azure SQL nicht vorhanden zu sein :-(
Simon_Weaver

1
Ich weiß, dass es nicht ernst gemeint ist, aber bitte, Sie verdrängen nur marginalisierte Gruppen von Engineering & Tech, wobei diese Argumentation überall wiederholt wird. Sie sollten beides lernen, aber Sie sollten die Leute nicht dafür bestrafen, dass sie zeitsparende Dienstprogramme verwenden, um intelligenter und schneller zu arbeiten. (Obwohl SSMS manchmal ein "Dienstprogramm zur Verlangsamung" zu sein scheint ...: X) Persönlich sind die Anzeigen für tabellarische Daten in einer GUI normalerweise klarer, obwohl von Microsoft erstellte Tools eher die Ausnahmen für alles sind, was mit der Benutzeroberfläche zu tun hat.
Julia McGuigan

102

Mit sp_spaceused erhalten Sie Informationen zum Speicherplatz, der von einer Tabelle, einer indizierten Ansicht oder der gesamten Datenbank verwendet wird.

Zum Beispiel:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

Hier werden die Informationen zur Datenträgernutzung für die ContactInfo-Tabelle angezeigt.

So verwenden Sie dies für alle Tabellen gleichzeitig:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

Sie können die Festplattennutzung auch über die Rechtsklick-Funktion "Standardberichte" von SQL Server abrufen. Um zu diesem Bericht zu gelangen, navigieren Sie im Objekt-Explorer vom Serverobjekt, gehen Sie zum Datenbankobjekt und klicken Sie mit der rechten Maustaste auf eine Datenbank. Wählen Sie im angezeigten Menü Berichte, dann Standardberichte und dann "Datenträgernutzung nach Partition: [Datenbankname]".


3
Dies ist ordentlich, obwohl die Verwendung sp_msforeachtablein SSMS leicht eine auslösen kann, System.OutOfMemoryExceptionwenn Sie eine große Anzahl von Tabellen haben. Daher ist es möglicherweise besser, eine temporäre Tabelle zum Speichern der Ergebnisse zu verwenden.
Syneticon-DJ

1
Das Hauptproblem, das ich bei sp_spacedused sehen kann, ist, dass es die Daten in einem für Menschen lesbaren Format zurückzugeben scheint (z. B. in der Spalte 'reserviert' in meinem Fall '152 KB'). Ich gehe davon aus, dass dies entsprechend auf MB / GB umgeschaltet wird. Dies ist in vielen Situationen eindeutig nützlich, aber nicht, wenn Sie eine Logik basierend auf der Größe anwenden müssen oder Werte oder was auch immer vergleichen möchten. Ich habe nach einer Möglichkeit gesucht, dies auszuschalten, aber ich konnte keine erkennen (ich verwende SQL Server 2005 :()
DarthPablo

55

Hier ist eine andere Methode: Gehen Sie mit SQL Server Management Studio im Objekt-Explorer zu Ihrer Datenbank und wählen Sie Tabellen aus

Geben Sie hier die Bildbeschreibung ein

Öffnen Sie dann die Objekt-Explorer-Details (entweder durch Drücken von F7 oder gehen Sie zu Ansicht-> Objekt-Explorer-Details ). Klicken Sie auf der Detailseite des Objekt-Explorers mit der rechten Maustaste auf die Spaltenüberschrift und aktivieren Sie die Spalten, die auf der Seite angezeigt werden sollen. Sie können die Daten auch nach einer beliebigen Spalte sortieren.

Geben Sie hier die Bildbeschreibung ein


Ja, SSMS in Azure verfügt im Vergleich zur lokalen Version über einige Funktionen.
Sparrow

@batmaci Ich bin mir nicht sicher, ob dies überhaupt funktioniert hat, als Sie Ihren Kommentar zu Azure SQL-Datenbanken abgegeben haben, aber es scheint jetzt zumindest teilweise in den neuesten Versionen von SSMS zu funktionieren. Für mich scheint die Abfrage nach Tabellenmetadaten abgelaufen zu sein, aber bevor dies der Fall ist, scheint sie einige (3-10) Tabellen zurückzugeben, einschließlich (zuverlässig) der ausgewählten Tabelle. Wählen Sie eine Tabelle aus und klicken Sie auf Aktualisieren, um die gewünschte Tabelle anzuzeigen, wenn sie nicht angezeigt wird.
PCDEV

Azure ist kein "echter" SQL Server (ha ha)
Reversed Engineer

Ich habe dies für Azure verwendet, danke mit einem (plus eins),
Irf

Sie können die Liste auch in eine CSV-Datei exportieren, indem Sie ein Dienstprogramm wie NirSoft SysExporter verwenden: nirsoft.net/utils/sysexp.html
Max

39

Nach einiger Suche konnte ich keine einfache Möglichkeit finden, Informationen zu allen Tabellen zu erhalten. Es gibt eine praktische gespeicherte Prozedur mit dem Namen sp_spaceused, die den gesamten von der Datenbank verwendeten Speicherplatz zurückgibt. Wenn ein Tabellenname angegeben wird, wird der von dieser Tabelle verwendete Speicherplatz zurückgegeben. Die von der gespeicherten Prozedur zurückgegebenen Ergebnisse sind jedoch nicht sortierbar, da die Spalten Zeichenwerte sind.

Das folgende Skript generiert die gesuchten Informationen.

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

Nachdem ich das Obige mit foreach gesehen hatte und der SP so etwas schreiben wollte, war ich froh, dass ich nach unten gescrollt habe, um zu sehen, dass es mir ein bisschen Zeit gespart hat.
Brad

37
 exec  sp_spaceused N'dbo.MyTable'

Verwenden Sie für alle Tabellen .. (aus den Kommentaren von Paul)

exec sp_MSForEachTable 'exec sp_spaceused [?]'

5
Sneaky - Sie veränderte sich von exec sp_helpdbdenen nicht zeigen nichts über Tabellen, zu exec sp_spaceuseddenen tut - aber nur für eine Tabelle zu einer Zeit ... es nicht Sie einen Überblick über das , was Tabellen Sie haben und wie viel Reihen sie haben und wie viel Platz nehmen sie ein.
marc_s

4
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Paul

27

Die obigen Abfragen eignen sich gut zum Ermitteln des von der Tabelle verwendeten Speicherplatzes (einschließlich Indizes). Wenn Sie jedoch vergleichen möchten, wie viel Speicherplatz von Indizes in der Tabelle verwendet wird, verwenden Sie diese Abfrage:

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

Was ist der Grund, warum das Aufsummieren der Spalte Indexgröße (KB) für eine bestimmte Tabelle nicht mit der Indexgröße von sp_spaceused übereinstimmt?
Derek

@Derek Korrigierte seine Antwort durch Hinzufügen where [i].[is_primary_key] = 0. Jetzt sollten die Größen übereinstimmen.
CodeAngry

Danke, aber das klappt auch nicht. Ich habe eine (sehr kleine) Testdatenbank. Die interessierende Tabelle enthält zwei Indizes - einen primären Clustered-Index für eine Spalte und einen Nicht-Clustered-Index für zwei der anderen Spalten. Diese Abfrage besagt, dass jeder von ihnen 16 KB verwendet, aber sp_spaceused gibt an, dass die gesamte Indexnutzung 24 KB beträgt. Ein Teil meiner Verwirrung ist folgender: Wenn ich diese Abfrage mit dem "UsedSpaceKB" der akzeptierten Antwort vergleiche, sehe ich keinen wirklichen Unterschied. Gleiche Verknüpfungen, nur das Hinzufügen von sys.tables fehlt. Vermisse ich etwas oder ist diese Abfrage von Natur aus fehlerhaft?
Derek

Ich habe große Datenbanken. Und Größen passen zu sp_spaceused. Ich messe GBs, so dass ein paar Megas, die nicht übereinstimmen, nicht viel sind. Die genauen Größen sind mir egal, nur eine Idee.
CodeAngry

14

Wenn Sie genau dieselben Zahlen berechnen müssen, die sich in SSMS auf der Seite "Tabelleneigenschaften - Speicher" befinden, müssen Sie sie mit derselben Methode zählen wie in SSMS (funktioniert für SQL Server 2005 und höher ... und auch) funktioniert korrekt für Tabellen mit LOB-Feldern - da das bloße Zählen von "used_pages" nicht ausreicht, um die genaue Indexgröße anzuzeigen):

;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

Erweiterung auf @ xav- Antwort , die Tabellenpartitionen verarbeitet, um die Größe in MB und GB zu ermitteln. Getestet auf SQL Server 2008/2012 (Kommentar in einer Zeile, in der 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

auch bessere Sortierreihenfolge.
Pxtl

Dies sollte die beste Antwort sein.
Baodad

14

Für Azure habe ich Folgendes verwendet:

Sie sollten SSMS v17.x haben

Ich benutzte;

Geben Sie hier die Bildbeschreibung ein

Damit hat User Sparrow Folgendes erwähnt :

Öffnen Sie Ihr Databases> und wählen Sie Tabellen .
Drücken Sie dann die Taste F7. Sie sollten Folgendes sehen row count
: Geben Sie hier die Bildbeschreibung ein

SSMS ist hier mit Azure-Datenbanken verbunden


3
F7 wird stark unterbeansprucht.
Cskwg

1
Ich hatte keine Ahnung, dass es das gibt, ich schäme mich ein bisschen für mich selbst: p Danke!
Lollancf37

Es hat ein Problem mit speicheroptimierten Tabellen (ich habe es gerade getestet, nachdem ich diesen Beitrag gesehen habe :)
Amirreza

11

Wir verwenden die Tabellenpartitionierung und hatten aufgrund doppelter Datensätze Probleme mit den oben angegebenen Abfragen.

Für diejenigen, die dies benötigen, finden Sie unten die Abfrage, die von SQL Server 2014 ausgeführt wird, wenn der Bericht "Datenträgerverwendung nach Tabelle" generiert wird. Ich gehe davon aus, dass es auch mit früheren Versionen von SQL Server funktioniert.

Es wirkt wie ein Zauber.

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

Vielen Dank für ein Skript, das der Funktionsweise von SSMS entspricht und Partitionen ordnungsgemäß verarbeitet.
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

Eine kleine Änderung in Mar_cs Antwort , da ich so oft auf diese Seite zurückgegangen bin, geordnet nach den meisten Zeilen zuerst:

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

Dadurch erhalten Sie die Größen und die Anzahl der Datensätze für jede Tabelle.

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
Wenn Sie Code-, XML- oder Datenbeispiele veröffentlichen, markieren Sie diese Zeilen BITTE im Texteditor und klicken Sie auf die Schaltfläche "Codebeispiele" ( { }) in der Editor-Symbolleiste, um sie gut zu formatieren und in der Syntax hervorzuheben!
marc_s

4

Um alle Tabellengrößen in einer Datenbank abzurufen, können Sie folgende Abfrage verwenden:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

Sie können es ändern, um das gesamte Ergebnis in die temporäre Tabelle einzufügen, und anschließend aus der temporären Tabelle auswählen.

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

3

An einer Eingabeaufforderung mit OSQL :

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

3

Mit den folgenden Schritten können Sie die Größe aller Tabellen schnell ermitteln:

  1. Schreiben Sie die angegebenen T-SQL-Befehle, um alle Datenbanktabellen aufzulisten:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. Kopieren Sie nun die Liste der Datenbanktabellen und kopieren Sie sie in ein neues Query Analyzer-Fenster

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. Wählen Sie im SQL Query Analyzer aus der oberen Symbolleiste die Option Ergebnisse in Datei ( Ctrl+ Shift+ F).

  4. Nun endlich auf die Execute roten Knopf von oben markiert Werkzeugleiste .

  5. Die Datenbankgröße aller Tabellen wird jetzt in einer Datei auf Ihrem Computer gespeichert.

    Geben Sie hier die Bildbeschreibung ein


2

Ich habe ein paar weitere Spalten über marc_s Antwort hinzugefügt:

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

Mein Beitrag ist nur für SQL Server 2000 relevant und wurde getestet, um in meiner Umgebung zu funktionieren.

Dieser Code greift auf alle möglichen Datenbanken einer einzelnen Instanz zu , nicht nur auf eine einzelne Datenbank.

Ich verwende zwei temporäre Tabellen, um die entsprechenden Daten zu sammeln und die Ergebnisse dann in einer 'Live'-Tabelle abzulegen.

Zurückgegebene Daten sind: DatabaseName, DatabaseTableName, Zeilen (in der Tabelle), Daten (Größe der Tabelle in KB, wie es scheint), Eingabedaten (ich finde dies nützlich, um zu wissen, wann ich das Skript zuletzt ausgeführt habe).

Der Nachteil dieses Codes ist, dass das Feld 'data' nicht als int gespeichert wird (die Zeichen 'KB' werden in diesem Feld gespeichert), und dies wäre nützlich (aber nicht unbedingt erforderlich) für die Sortierung.

Hoffentlich hilft dieser Code jemandem da draußen und spart ihm Zeit!

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] 

Falls Sie wissen müssen, wurde die Tabelle rsp_DatabaseTableSizes erstellt durch:

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

GO

1

Als einfache Erweiterung der Antwort von marc_s (die angenommen wurde) wird diese angepasst, um die Spaltenanzahl zurückzugeben und das Filtern zu ermöglichen:

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

Nachdem Sie der Columns-Tabelle beigetreten sind, haben Sie nicht mehr den richtigen Tabellenbereich. Äußere Anwendung wird die Lösung sein.
Dreamca4er

0

Beim Riffing der obigen @ Mark-Antwort wurde @ updateusage = 'true' hinzugefügt, um die neuesten Größenstatistiken zu erzwingen ( 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

Hier ist eine Beispielabfrage, um Tabellen größer als 1 GB nach absteigender Größe zu erhalten.

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.