如何在SQL Server数据库中查找最大的对象?


136

我将如何查找SQL Server数据库中最大的对象?首先,通过确定哪些表(和相关索引)最大,然后确定特定表中的哪些行最大(我们将二进制数据存储在BLOB中)?

是否有任何工具可以帮助进行这种数据库分析?还是有一些我可以针对系统表运行的简单查询?

Answers:


280

我一直在使用这个SQL脚本(我是从某个地方的某人那里获得的-无法重构它的来源),已经有很长一段时间了,它帮助我了解和确定了索引和表的大小:

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) 

当然,您可以使用其他订购条件,例如

ORDER BY SUM(p.rows) DESC

获取具有最多行的表,或者

ORDER BY SUM(a.total_pages) DESC

以获取使用最多页面(8K块)的表。


非常好,谢谢!现在,我将最大的对象缩小为一个包含大量二进制数据的表,无论如何找出二进制数据的哪几行最大?
jamesaharvey 2010年

3
为此,您必须在该表上进行选择并为您感兴趣的每个字段(通常为VARCHAR(MAX),VARBINARY(MAX)等)打印DATALENGTH(field)
marc_s

1
感谢@marc_s,这非常有用。TableName列还可以使用SELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen 2013年

2
那一定是我见过的最漂亮的TSQL脚本
Agustin Meriles

2
要也包括NON-CLUSTERED索引,请从WHERE子句中删除“和i.index_id <= 1”。
Gordon Bell

72

在SQL Server 2008中,您也可以只运行标准报告“按表排序的磁盘使用情况”。可以通过右键单击数据库,选择“报告”->“标准报告”并选择所需的报告来找到。


8
不开玩笑吗?这是一个革命性的答案。感谢您发布。(不是讽刺的。已经手动运行这些查询已有一段时间了,我不敢相信这些报告已经存在!)
Jennifer Zouak 2015年

4

此查询帮助您查找正在连接的最大表。

SELECT  TOP 1 OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

拥有我们可以轻松记住的东西是很好的。感谢您的简洁。
David Betz

3

您还可以使用以下代码:

USE AdventureWork
GO
CREATE TABLE #GetLargest 
(
  table_name    sysname ,
  row_count     INT,
  reserved_size VARCHAR(50),
  data_size     VARCHAR(50),
  index_size    VARCHAR(50),
  unused_size   VARCHAR(50)
)

SET NOCOUNT ON

INSERT #GetLargest

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT 
  a.table_name,
  a.row_count,
  COUNT(*) AS col_count,
  a.data_size
  FROM #GetLargest a
     INNER JOIN information_schema.columns b
     ON a.table_name collate database_default
     = b.table_name collate database_default
       GROUP BY a.table_name, a.row_count, a.data_size
       ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC

DROP TABLE #GetLargest

2

如果使用的是Sql Server Management Studio 2008,则可以在对象资源管理器详细信息窗口中查看某些数据字段。只需浏览并选择表格文件夹。在详细信息视图中,您可以右键单击列标题并将字段添加到“报告”中。如果您乘坐SSMS 2008 Express,则里程可能会有所不同。


2

我发现此查询在SqlServerCentral中也非常有用,这是原始文章的链接

SQL Server最大表

  select name=object_schema_name(object_id) + '.' + object_name(object_id)
, rows=sum(case when index_id < 2 then row_count else 0 end)
, reserved_kb=8*sum(reserved_page_count)
, data_kb=8*sum( case 
     when 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 )
, index_kb=8*(sum(used_page_count) 
    - sum( case 
           when 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 )
     )    
, unused_kb=8*sum(reserved_page_count-used_page_count)
from sys.dm_db_partition_stats
where object_id > 1024
group by object_id
order by 
rows desc   

在我的数据库中,他们在此查询和第一个答案之间给出了不同的结果。

希望有人觉得有用


1

@marc_s的答案非常好,我已经使用了几年了。但是,我注意到该脚本错过了某些列存储索引中的数据,并且没有显示完整的图片。例如,当您SUM(TotalSpace)对脚本进行操作并将其与Management Studio中的总空间数据库属性进行比较时,在我的情况下数字不匹配(Management Studio显示较大的数字)。我修改了脚本以解决此问题,并对其进行了扩展:

select
    tables.[name] as table_name,
    schemas.[name] as schema_name,
    isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown') as database_name,
    sum(allocation_units.total_pages) * 8 as total_space_kb,
    cast(round(((sum(allocation_units.total_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as total_space_mb,
    sum(allocation_units.used_pages) * 8 as used_space_kb,
    cast(round(((sum(allocation_units.used_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as used_space_mb,
    (sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8 as unused_space_kb,
    cast(round(((sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8) / 1024.00, 2) as numeric(36, 2)) as unused_space_mb,
    count(distinct indexes.index_id) as indexes_count,
    max(dm_db_partition_stats.row_count) as row_count,
    iif(max(isnull(user_seeks, 0)) = 0 and max(isnull(user_scans, 0)) = 0 and max(isnull(user_lookups, 0)) = 0, 1, 0) as no_reads,
    iif(max(isnull(user_updates, 0)) = 0, 1, 0) as no_writes,
    max(isnull(user_seeks, 0)) as user_seeks,
    max(isnull(user_scans, 0)) as user_scans,
    max(isnull(user_lookups, 0)) as user_lookups,
    max(isnull(user_updates, 0)) as user_updates,
    max(last_user_seek) as last_user_seek,
    max(last_user_scan) as last_user_scan,
    max(last_user_lookup) as last_user_lookup,
    max(last_user_update) as last_user_update,
    max(tables.create_date) as create_date,
    max(tables.modify_date) as modify_date
from 
    sys.tables
    left join sys.schemas on schemas.schema_id = tables.schema_id
    left join sys.indexes on tables.object_id = indexes.object_id
    left join sys.partitions on indexes.object_id = partitions.object_id and indexes.index_id = partitions.index_id
    left join sys.allocation_units on partitions.partition_id = allocation_units.container_id
    left join sys.dm_db_index_usage_stats on tables.object_id = dm_db_index_usage_stats.object_id and indexes.index_id = dm_db_index_usage_stats.index_id
    left join sys.dm_db_partition_stats on tables.object_id = dm_db_partition_stats.object_id and indexes.index_id = dm_db_partition_stats.index_id
group by schemas.[name], tables.[name], isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown')
order by 5 desc

希望对某人有帮助。该脚本已针对具有数百种不同表,索引和架构的大型TB级数据库进行了测试。

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.