您的位置:首页 > 移动开发 > Objective-C

分析表无索引为什么sp_spaceused 中的index_size不为0

2009-10-18 22:25 246 查看
源于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 
<
 
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
  



   ),  



  
@rowCount
 
=
 
SUM
 (  



   
CASE
  



    
WHEN
 (index_id 
<
 
2

THEN
 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
,
204

AND
 p.
object_id
 
=
 it.
object_id
;  



 
END
  



  



 
SELECT
   



  name 
=
 
OBJECT_NAME
 (
@id
),  



  rows 
=
 
convert
 (
char
(
11
), 
@rowCount
),  



  reserved 
=
 
LTRIM
 (
STR
 (
@reservedpages
 
*
 
8

15

0

+
 
'
 KB
'
),  



  data 
=
 
LTRIM
 (
STR
 (
@pages
 
*
 
8

15

0

+
 
'
 KB
'
),  



  index_size 
=
 
LTRIM
 (
STR
 ((
CASE
 
WHEN
 
@usedpages
 
>
 
@pages
 
THEN
 (
@usedpages
 
-
 
@pages

ELSE
 
0
 
END

*
 
8

15

0

+
 
'
 KB
'
),  



  unused 
=
 
LTRIM
 (
STR
 ((
CASE
 
WHEN
 
@reservedpages
 
>
 
@usedpages
 
THEN
 (
@reservedpages
 
-
 
@usedpages

ELSE
 
0
 
END

*
 
8

15

0

+
 
'
 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

*
 
8

15

0

+
 
'
 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看到:Pagetype=10为IAM PAGE



如有错误,欢迎指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息