获取数据库中所有表的大小


1271

我继承了一个相当大的SQL Server数据库。给定包含的数据,它似乎比我期望的要占用更多的空间。

有没有一种简单的方法来确定每个表占用多少磁盘空间?


您可以访问哪些角色?您是DBA,还是通过Web主机,客户端或类似服务器进行管理?
罗布·艾伦


@RobAllen我具有数据库的完全访问权限,因此需要任何角色的脚本就足够了。
埃里克(Eric)


对于Azure,我使用了
Irf,

Answers:


2592
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
愚蠢的问题,但是此查询是否可能导致行锁定?
GEMI

7
索引也使用空间,可以在下面的此查询中找到索引使用的空间量。
詹斯·弗兰德森

6
您的脚本存在过滤索引的问题:对于给定表的每个过滤索引,我在结果中看到带有该表名称的额外一行。这些额外行中的每一个的“ RowCounts”对应于被过滤索引之一覆盖的行数。(在Sql2012上)
Akos

37
@Todd:有些人希望它按这种方式排序-其他人希望按表名进行排序-随便您选择,并根据需要修改代码...
marc_s 2014年

12
如果您的表已分区,它们会多次显示而不会指示正在发生什么。您可以将p.partition_number添加到选择列表中,也可以SUM(p.Rows)并将其从分组依据中删除。
PRMan 2014年

561

如果您使用的是SQL Server Management Studio(SSMS),则可以运行标准报告,而不是运行查询(在我的情况下返回重复的行)。 

  1. 右键单击数据库
  2. 导航对报告>标准报告>按表的磁盘使用情况

注意:数据库兼容性级别必须设置为90或更高,才能正常工作。请参阅http://msdn.microsoft.com/en-gb/library/bb510680.aspx


54
在Management Studio 2012中,您可以执行以下操作:查看对象资源管理器详细信息(F7)并导航至对象资源管理器中的“表”。在“详细信息”中,右键单击标题,然后选择“大小”列。
ValGe 2014年

3
为建议使用SSMS 2012的新功能提供帮助。对于我们老练的人,我们从来没有此功能。因此,我们只是按照旧的TSQL方法进行操作:)
GoldBishop

3
信不信由你,有时候凡人(开发人员)都希望看到此信息,我们没有使用内置报告的权限,但我们可以在接受的答案中运行TSQL。:)仅供参考(顺便说一句,顺便说一句,我仍然支持你的回答)
安德鲁·

8
在Azure SQL中似乎不存在:-(
Simon_Weaver

1
我知道这并不严重,但是,请您将这种边缘化的观点在各地重复出现,从而将工程学和技术领域的边缘化群体推开。您应该两者都学,但是不要因为使用节省时间的实用程序而使人们变得更聪明,更快地工作而受到责难。(尽管SSMS有时似乎是一个“减速工具” ...:X)就个人而言,表格数据的读出通常在GUI中更为清晰,尽管Microsoft内置的工具往往是所有与UI相关的例外。
朱莉娅·麦圭根

102

sp_spaceused可以为您提供有关表,索引视图或整个数据库使用的磁盘空间的信息。

例如:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

这将报告ContactInfo表的磁盘使用情况信息。

要一次将其用于所有表:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

您还可以从SQL Server的“标准报表”功能的右键单击中获取磁盘使用情况。要获取此报告,请从“对象资源管理器”中的服务器对象导航,向下移至“数据库”对象,然后右键单击任何数据库。从出现的菜单中,选择“报告”,然后选择“标准报告”,然后选择“按分区划分的磁盘使用情况:[数据库名称]”。


3
这很简洁,尽管如果您有大量表,则sp_msforeachtable在SSMS中轻松使用可能会触发System.OutOfMemoryException,因此使用临时表存储结果可能是一个更好的主意。
syneticon-dj 2014年

1
我可以用sp_spacedused看到的主要问题是,它似乎以人类可读的格式返回了数据(例如,在我的例子中的“ reserved”列中,它具有“ 152 KB”)。我认为这将适当地切换为MB / GB。显然,这在许多情况下很有用,但如果您需要根据大小应用某些逻辑,或者想比较值或其他值,则无济于事。我正在寻找一种方法来关闭它,但是我找不到一个(我正在使用SQL Server 2005 :()
DarthPablo

55

这是另一种方法:使用SQL Server Management Studio,在“ 对象资源管理器”中,转到数据库并选择“ 表”

在此处输入图片说明

然后打开“ 对象资源管理器详细信息”(通过按F7或转到“ 视图”->“对象资源管理器详细信息”)。在对象资源管理器详细信息页面中,右键单击列标题,然后启用要在页面中看到的列。您也可以按任何列对数据进行排序。

在此处输入图片说明


是的,与本地版本相比,Azure中的SSMS缺少某些功能。
Sparrow

@batmaci当您对Azure SQL数据库发表评论时,不确定这是否完全起作用,但是在最新版本的SSMS中,现在似乎至少部分起作用。对我来说,似乎对表元数据的查询已超时,但在此之前,它似乎返回了几(3-10)张值得的表,包括(可靠地)选定的表。选择一个表,然后单击刷新以查看所需的表(如果未显示)。
pcdev

Azure不是“真正的” SQL Server(哈哈)
反向工程师,

我将用于Azure,感谢(加1),
Irf

您也可以使用NirSoft SysExporter之类的实用程序将列表导出为CSV文件:nirsoft.net/utils/sysexp.html
Max

39

经过一番搜索,我找不到一种简单的方法来获取所有表的信息。有一个名为sp_spaceused的方便的存储过程,该过程将返回数据库使用的所有空间。如果提供了表名,则返回该表使用的空间。但是,由于列是字符值,所以存储过程返回的结果不可排序。

以下脚本将生成我正在寻找的信息。

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

在使用foreach看到以上内容之后,SP将编写类似这样的内容,很高兴我向下滚动以查看它节省了一些时间。
布拉德,

37
 exec  sp_spaceused N'dbo.MyTable'

对于所有表,使用..(从Paul的注释中添加)

exec sp_MSForEachTable 'exec sp_spaceused [?]'

5
偷偷摸摸的 -您从exec sp_helpdb什么都没有显示表的内容更改为- 什么都exec sp_spaceused没有-但一次只更改了一张表...它并没有为您提供有关哪些表以及它们有多少行以及如何概览的概述他们占用了很多空间。
marc_s

4
exec sp_MSForEachTable'exec sp_spaceused [?]'
Paul

27

以上查询非常适合查找表使用的空间量(包括索引),但是如果要比较表上索引使用的空间量,请使用以下查询:

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

对特定表的Indexsize(KB)列求和与sp_spaceused中的index_size不符的原因是什么?
德里克(Derek)

@Derek通过添加修复了他的答案where [i].[is_primary_key] = 0。现在大小应该匹配。
CodeAngry

谢谢,但这实际上也不可行。我有一个(很小的)测试数据库,感兴趣的表有两个索引-一个列上的主聚集索引和另一个列上的两个非聚集索引。该查询说它们每个都使用16kB,但是sp_spaceused说总索引使用量是24kB。我的困惑部分在于:将查询与接受的答案的“ UsedSpaceKB”进行比较,我看不出真正的区别。相同的联接,只是缺少sys.tables的添加。我是否缺少某些内容,或者此查询固有地损坏了?
德里克(Derek)

我有大型数据库。且尺寸与匹配sp_spaceused。我测量GB,所以不匹配的兆字节不多。我不在乎确切的大小,只是一个想法。
CodeAngry

14

如果需要计算SSMS中“表属性-存储”页面上完全相同的数字,则需要使用与SSMS中相同的方法对它们进行计数(适用于sql server 2005及更高版本...以及对于具有LOB字段的表可以正常工作-因为仅计算“ used_pa​​ges”不足以显示准确的索引大小):

;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

@xav 答案的扩展名,用于处理表分区以获取MB和GB的大小。在SQL Server 2008/2012上进行了测试(在中注释了一行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

也更好的排序顺序。
Pxtl

这应该是最佳答案。
鲍达德

14

对于Azure,我使用了以下方法:

您应该拥有SSMS v17.x

我用了;

在此处输入图片说明

正如用户 Sparrow所说的

打开Databases>并选择Tables
然后按F7键, 您应该看到row count
在此处输入图片说明

这里的 SSMS 已连接到Azure数据库


3
F7未被充分利用。
cskwg

1
我不知道这是存在的,我为自己感到羞愧:p谢谢!
lollancf37

它具有内存优化表的问题,(我在看完这篇文章后才进行了测试:)
Amirreza

11

我们使用表分区,由于记录重复,上面提供的查询有些麻烦。

对于需要此功能的用户,可以在生成“按表使用磁盘”报告时在SQL Server 2014运行的查询下方找到。我认为它也可以与早期版本的SQL Server一起使用。

它像一种魅力。

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

感谢您提供一个与SSMS的运行方式相匹配并能够正确处理分区的脚本。
麦克,

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

Mar_c的答案有一个小变化,因为我经常返回此页面,并且按大多数行的第一顺序进行排序:

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

这将为您提供大小,并记录每个表的计数。

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
如果发布代码,XML或数据示例,在文本编辑器中突出显示这些行,然后单击{ }编辑器工具栏上的“代码示例”按钮(),以很好地格式化和语法突出显示它!
marc_s

4

要在一个数据库中获取所有表的大小,可以使用以下查询:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

您可以更改它以将所有结果插入到临时表中,然后从临时表中选择。

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

3

在使用OSQL的命令提示符下:

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

3

这是一种通过以下步骤快速获取所有表大小的方法:

  1. 编写给定的T-SQL命令以列出所有数据库表:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. 现在复制数据库表的列表,并将其复制到新的查询分析器窗口中

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. 在SQL 查询分析器中,从顶部工具栏选项中选择结果到文件Ctrl+ Shift+ F)。

  4. 现在,最后点击上方工具栏上标记为红色的“ 执行”按钮。

  5. 现在,所有表的数据库大小都存储在计算机上的文件中。

    在此处输入图片说明


2

我在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

我的帖子仅与SQL Server 2000相关,并且已经过测试,可以在我的环境中工作。

此代码访问单个实例的所有可能的数据库,而不仅仅是单个数据库。

我使用两个临时表来帮助收集适当的数据,然后将结果转储到一个“实时”表中。

返回的数据是:DatabaseName,DatabaseTableName,行(在表中),数据(表的大小以KB表示),条目数据(我发现这对我上次运行脚本的时间很有用)。

该代码的缺点是'data'字段未存储为int(字符'KB'保留在该字段中),这对于排序很有用(但并非完全必要)。

希望这段代码可以帮助某个人并节省一些时间!

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] 

如果您需要知道,rsp_DatabaseTableSizes表是通过以下方式创建的:

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

GO

1

作为对marc_s答案(已被接受的答案)的简单扩展,将其调整为返回列数并允许过滤:

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

加入Columns表后,您将失去合适的表空间。外层应用将解决此问题。
dreamca4er

0

在上面的@Mark回答中,添加了@ updateusage ='true'以强制使用最新的大小统计信息(https://msdn.microsoft.com/zh-cn/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

这是一个示例查询,用于获取按大小降序排列的大于1GB的表。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.