zoukankan      html  css  js  c++  java
  • 表无索引为什么sp_spaceused 中的index_size不为0

    源于csdn论坛的一个提问:

    CREATE TABLE TUser ( FName CHAR(8000), FAge INT, FSex bit )
    INSERT INTO TUser
    SELECT '张三',18,1 UNION ALL
    SELECT '李四',20,1 UNION ALL
    SELECT '王五',32,1 UNION ALL
    SELECT '麻子',23,1

     
    通过一个查询看下扫描的数据页:

    SET STATISTICS IO ON
    SELECT * FROM TUser
    /*
    (4 行受影响)
    表 'TUser'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    */

    可以看到,该查询全部数据是扫了四个数据页,也就是说插入的四行数据,一行为一个page.

     但是我们执行下面的sql,发现index_size为8k:

    EXEC sp_spaceused N'TUser'
    /*
    name    rows        reserved    data    index_size    unused
    TUser    4              40 KB        32 KB    8 KB        0 KB
    */

     这是为什么,为什么没有建索引,这里却有一个index_size 8k ?

    下面来看看index_size是怎么来的?
    首先想到是的

    sp_helptext sp_spaceused

    通过查看sp_spaceused的代码,我们找到对于我们这个查询有用的信息代码:

     /*  
     ** Now calculate the summary data.   
     *  Note that LOB Data and Row-overflow Data are counted as Data Pages.  
     
    */
      
     
    SELECT   
      
    @reservedpages = SUM (reserved_page_count),  
      
    @usedpages = SUM (used_page_count),  
      
    @pages = SUM (  
       
    CASE  
        
    WHEN (index_id < 2THEN (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  
       ),  
      
    @rowCount = SUM (  
       
    CASE  
        
    WHEN (index_id < 2THEN row_count  
        
    ELSE 0  
       
    END  
       )  
     
    FROM sys.dm_db_partition_stats  
     
    WHERE object_id = @id;  
      
     
    /*  
     ** Check if table has XML Indexes or Fulltext Indexes which use internal tables tied to this table  
     
    */
      
     
    IF (SELECT count(*FROM sys.internal_tables WHERE parent_id = @id AND internal_type IN (202,204)) > 0   
     
    BEGIN  
      
    /*  
      **  Now calculate the summary data. Row counts in these internal tables don't   
      **  contribute towards row count of original table.    
      
    */
      
      
    SELECT   
       
    @reservedpages = @reservedpages + sum(reserved_page_count),  
       
    @usedpages = @usedpages + sum(used_page_count)  
      
    FROM sys.dm_db_partition_stats p, sys.internal_tables it  
      
    WHERE it.parent_id = @id AND it.internal_type IN (202,204AND p.object_id = it.object_id;  
     
    END  
      
     
    SELECT   
      name 
    = OBJECT_NAME (@id),  
      rows 
    = convert (char(11), @rowCount),  
      reserved 
    = LTRIM (STR (@reservedpages * 8150+ ' KB'),  
      data 
    = LTRIM (STR (@pages * 8150+ ' KB'),  
      index_size 
    = LTRIM (STR ((CASE WHEN @usedpages > @pages THEN (@usedpages - @pagesELSE 0 END* 8150+ ' KB'),  
      unused 
    = LTRIM (STR ((CASE WHEN @reservedpages > @usedpages THEN (@reservedpages - @usedpagesELSE 0 END* 8150+ ' KB'

    通过上面的代码,我们可以基于我们目前的这个情况(堆表,不含有xml和fulltext,所以上面的202/204那段不用管了)提练出index的page如下算法:

    select index_pagecount=sum(used_page_count)-
    sum(in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
    from sys.dm_db_partition_stats  
    where object_id = object_id('TUser'); 

    这个结果是1.再套上index_size的公式:

    select index_size = LTRIM (STR ((1* 8150+ ' KB')
    /*
    8k
    */

    这就是8k的算法,从下面联机文档上关于sys.dm_db_partition_stats 的解释,可以分析出这个8k是个IAM page.
    used_page_count  bigint
    用于分区的总页数。计算方法为 in_row_used_page_count + lob_used_page_count + row_overflow_used_page_count

    上面我们算index_page时公式为:
    sum(used_page_count)-
    sum(in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
    也就是in_row_used_page_count -in_row_data_page_count
    对于这两列,联机文档解释是:

    in_row_used_page_count

    用于存储和管理分区中的行内数据的总页数。该计数包括非叶 B 树页、IAM 页以及 in_row_data_page_count 列包含的全部页。

    in_row_data_page_count

    分区中存储行内数据所用的页数。如果分区是堆的一部分,则该值为堆中的数据页数。如果分区是索引的一部分,则该值为叶级别中的页数。(未计入 B 树中非叶页的数目。)以上两种情况都未计入 IAM(索引分配映射)页。

    针对我们目前该表的情况,仅是一个堆表,那么可知前者是包含了IAM页,而后者不含有IAM页,那么sp_spaceused中的index_size在这里就是一个IAM(索引分配映射)页。

    其实这个也可以通过DBCC IND看到:

    如有错误,欢迎指正。


     
     


    作者:nzperfect
    出处:http://www.cnblogs.com/nzperfect/
    引用或者转载本BLOG的文章请注明原作者和出处,并保留原文章中的版权信息。

  • 相关阅读:
    上传文件事件并校验:event.target.files && event.target.files[0]
    深浅拷贝
    Git学习
    Flex弹性布局
    hive
    222
    错误总结
    Redis小结2
    spark小结
    kafka详解
  • 原文地址:https://www.cnblogs.com/nzperfect/p/1585641.html
Copyright © 2011-2022 走看看