怎么知道一行记录占用了多大的硬盘空间?
--> 用系统函数sys.dm_db_index_physical_stats() 
    参考http://technet.microsoft.com/zh-cn/library/ms188917(v=sql.105).aspx索引、主键这样怎么知道一共占用了多少?
--> use [数据库名]sp_spaceused '[表名]'

解决方案 »

  1.   

    这个精确的值不好计算,不过可以求个平均值的。比如:--返回占用的空间
    sp_spaceused '你的表'
    go
    --返回行数
    select distinct rows
    from sys.partitions
    where object_id = object_id('你的表')然后   每一行的大小 = 空间大小/行数
      

  2.   

    没法知道。数据库的物理存储很复杂。我无意于去解释这一点,只是用一个简单的例子说明为什么无法知道。比如说,我们为了保证数据的连续存储和寻址,采用分块的方式存储。比如,当我们新插入一个数据,我们会请求100个数据的连续存储区域,保存在第一个位置上。当我们插入第二个数据,那么此时我们无需申请新的存储,还是使用之前的存储区域,将数据存入第二个位置……当我们插入101条数据,我们会请求2个这样的块,也就是200个数据的存储区域。那么从外部看,仿佛第一个数据占用了100条数据的空间,第2~100条不需要任何存储空间,第101条又需要100个数据的空间。或者说当你连续插入数据,你会观察到数据库的存储并非线性的增长,而是阶梯式的增长。当然,这只是一个举例。总之,除非你是数据库的设计者,了解全部的算法,否则不可能得知这一点。数据库的设计者为了性能的调优和增加功能/修复bug,也不排除不断修正数据库的存储算法,出于向前兼容的需要,他们也不可能公开这样的API去计算究竟一条记录占用多少存储这样的API。相反,数据库往往提供了压缩、整理的功能,压缩、整理的前后数据是一样的,数据库占用的存储是不一样的,这显然说明数据占用的存储和数据本身并非直接相关。
      

  3.   

    你如果要最精确的数据的话,可能只有DBCC PAGE这个命令来算,不过如果作为测试,可以清空一下buffer ,然后查一下某个表的数据,最好不要出现扫描操作,这是为了知道加载了多少行到buffer,然后如果是2008的话,可以用下面语句粗略查一下buffer的大小,然后除以行数:
    --Buffer Pool的内存主要是由那个数据库占了?
    SELECT  COUNT(*) * 8 AS cached_pages_kb ,
            CASE database_id
              WHEN 32767 THEN 'ResourceDb'
              ELSE DB_NAME(database_id)
            END AS Database_name
    FROM    sys.dm_os_buffer_descriptors
    GROUP BY DB_NAME(database_id) ,
            database_id
    ORDER BY cached_pages_kb DESC;
    --当前数据库的哪个表或者索引占用Pool缓冲空间最多?
    SELECT  COUNT(*) * 8 AS cached_pages_kb ,
            obj.name ,
            obj.index_id ,
            b.type_desc ,
            b.name
    FROM    sys.dm_os_buffer_descriptors AS bd
            INNER JOIN ( SELECT OBJECT_NAME(object_id) AS name ,
                                index_id ,
                                allocation_unit_id ,
                                object_id
                         FROM   sys.allocation_units AS au
                                INNER JOIN sys.partitions AS p ON au.container_id = p.hobt_id
                                                                  AND ( au.type = 1
                                                                  OR au.type = 3
                                                                  )
                         UNION ALL
                         SELECT OBJECT_NAME(object_id) AS name ,
                                index_id ,
                                allocation_unit_id ,
                                object_id
                         FROM   sys.allocation_units AS au
                                INNER JOIN sys.partitions AS p ON au.container_id = p.partition_id
                                                                  AND au.type = 2
                       ) AS obj ON bd.allocation_unit_id = obj.allocation_unit_id
            LEFT JOIN sys.indexes b ON b.object_id = obj.object_id
                                       AND b.index_id = obj.index_id
    WHERE   database_id = DB_ID()
    GROUP BY obj.name ,
            obj.index_id ,
            b.name ,
            b.type_desc
    ORDER BY cached_pages_kb DESC;