【问题标题】:How to find largest objects in a SQL Server database?如何在 SQL Server 数据库中找到最大的对象?
【发布时间】:2011-01-06 20:33:51
【问题描述】:

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

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

【问题讨论】:

    标签: sql-server database


    【解决方案1】:

    多年来,我一直在使用这个 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 块)最多的表。

    【讨论】:

    • 太好了,谢谢!现在,我已经将最大的对象缩小到一个包含大量二进制数据的表中,无论如何要找出哪些二进制数据行是最大的?
    • 为此,您必须对该表进行选择并为您感兴趣的每个字段打印出 DATALENGTH(field)(通常为 VARCHAR(MAX)、VARBINARY(MAX) 和等等)
    • 感谢@marc_s,这非常有用。 TableName 列还可以包含带有SELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ... 的架构名称
    • 那一定是我见过最漂亮的TSQL脚本了
    • 要包含非聚集索引,请从 WHERE 子句中删除“and i.index_id
    【解决方案2】:

    在 SQL Server 2008 中,您也可以只运行按 Top Tables 划分的标准磁盘使用情况报告。这可以通过右键单击数据库,选择 Reports->Standard Reports 并选择所需的报告来找到。

    【讨论】:

    • 不开玩笑?这是一个革命性的答案。感谢您发布它。 (不是讽刺。手动运行这些查询已经有一段时间了,我不敢相信这些报告已经存在了!)
    【解决方案3】:

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

    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
    

    【讨论】:

    • 有一些我们可以轻松记住的东西是件好事。感谢您的简洁。
    【解决方案4】:

    您也可以使用以下代码:

    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
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        我发现这个查询在 SqlServerCentral 中也很有帮助,这里是原始帖子的链接

        Sql Server largest tables

          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   
        

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

        希望有人觉得有用

        【讨论】:

          【解决方案7】:

          @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 级数据库进行了测试。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-16
            • 2018-08-29
            • 2011-04-10
            • 2017-03-30
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多