索引的碎片处理

对于利用SqlServer作为数据库的应用程序而言,如果对性能有较高要求的话,索引碎片的处理是不可忽略的一个环节:

   
   
MSDN: http: // msdn.microsoft.com / zh - cn / library / ms189858.aspx
-- 索引的维护 提示(online的作用非常的大,聚集的重键会使表不能使用)
昨天经过kg牛牛的提示,想了点索引碎片的知识。随想随写,有点乱,也许有错的地方,csdner可以灰铁提示
SELECT OBJECT_NAME (dt. object_id ),
si.name,
dt.avg_fragmentation_in_percent,
dt.avg_page_space_used_in_percent
FROM
(
SELECT object_id ,
index_id,
avg_fragmentation_in_percent,
avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats ( DB_ID (), NULL , NULL , NULL , ' DETAILED ' )
WHERE index_id <> 0
)
AS dt -- does not return information about heaps
INNER JOIN sys.indexes si
ON si. object_id = dt. object_id
AND si.index_id = dt.index_id


碎片的分类
1内部碎片(avg_page_space_used_in_percent)
- 是说索引的大小,超过了索引的实际大小,也就是填充度
2外部碎片(avg_fragmentation_in_percent)
- 是说索引页面的排序和物理不一致, index page的newxtpage + prevpageid的是最小相临的(REORGANIZE就是解决这个问题)
3物理连续性(fragment_count 和 avg_fragment_size_in_pages
[ >65 and <256 ] - 是说单一的分配单元的8个页面的连续性质,简单可以说是nextpage是不是当前page的 + 1至 + 7
4内部的逻辑碎片(有聚集索引的情况) 也就是槽号的物理顺序和逻辑顺序的不同(就是很多人说的聚集索引的顺序,和物理的存储顺序是不同的)

ALTER INDEX [ index_id ] ON [ dbo ] . [ tbTest ] REORGANIZE
重新组织索引
REORGANIZE的过程:
1压缩过程 查找临近的page,查找可以移动的记录转移到小pageid的页面,增加填充度(不会分配新的index page,有些记录会因为移动,而不在先前的page里存放)
2使逻辑和物理的顺序保持一致(这和上面的不冲突),使用中间页来互换页面内容,使页面的pageid从小到大排列,删除最后的空page
ALTER INDEX [ index_id ] ON [ dbo ] . [ tbTest ] REBUILD
重键索引
同时维护2个索引,新的创建完,会删除旧索引(因为同时维护2个版本的索引,只能分配新的索引页面,删除旧的索引页面)
所以rebuild后的avg_fragmentation_in_percent逻辑碎片,应该是在0
- 3左右,avg_page_space_used_in_percent会在95以上(大型行也许会小一点)


-- 页拆分引起的碎片
if object_id ( ' tbTest ' ) is not null
drop table tbTest
go
create table tbTest(a int primary key ,b varchar ( 1600 ))
go
insert into tbtest(a,b) select 5 , replicate ( ' a ' , 1600 )
insert into tbtest(a,b) select 10 , replicate ( ' b ' , 1600 )
insert into tbtest(a,b) select 15 , replicate ( ' c ' , 1600 )
insert into tbtest(a,b) select 20 , replicate ( ' d ' , 1600 )
insert into tbtest(a,b) select 25 , replicate ( ' e ' , 1600 )

dbcc ind( [ index ] ,tbTest, 1 )

dbcc traceon( 3604 )

dbcc page( [ index ] , 1 , 45 , 1 )

insert into tbtest(a,b) select 22 , replicate ( ' f ' , 1600 )
用上面的查询看碎片的结果
(无列名) name avg_fragmentation_in_percent avg_page_space_used_in_percent
tbTest PK__tbTest__164452B1
50 59.9085742525327

dbcc page( [ index ] , 1 , 45 , 1 )
-- 内部碎片avg_page_space_used_in_percent
select ( 8096 - 3245 /* m_freeCnt */ ) * 1.0 / 8096 = 0.599184 基本可以对上
-- 逻辑碎片
avg_fragmentation_in_percent 这个的50,也许是 [ 物理连续性 ] 一类的碎片,因为外部的大小顺序倒是一样的,不深究了

dbcc page( [ index ] , 1 , 80 , 1 ) 。。。

-- 判断REORGANIZE和REBUILD,重新组织和重建索引(注意,text,varchar(max)等要特殊处理,下次再说...:))

SELECT t.name as tablename, ' ALTER INDEX [ ' + ix.name + ' ] ON [ ' + s.name + ' ].[ ' + t.name + ' ] ' +
CASE
WHEN ps.avg_fragmentation_in_percent > 15
THEN ' REBUILD '
ELSE ' REORGANIZE '
END +
CASE
WHEN pc.partition_count > 1
THEN ' PARTITION = ' + CAST (ps.partition_number AS nvarchar ( MAX ))
ELSE ''
END ,
avg_fragmentation_in_percent
FROM sys.indexes AS ix
INNER JOIN sys.tables t
ON t. object_id = ix. object_id
INNER JOIN sys.schemas s
ON t.schema_id = s.schema_id
INNER JOIN
(
SELECT object_id ,
index_id ,
avg_fragmentation_in_percent,
partition_number
FROM sys.dm_db_index_physical_stats ( DB_ID (), NULL , NULL , NULL , NULL )
) ps
ON t. object_id = ps. object_id
AND ix.index_id = ps.index_id
INNER JOIN
(
SELECT object_id ,
index_id ,
COUNT ( DISTINCT partition_number) AS partition_count
FROM sys.partitions
GROUP BY object_id ,
index_id
) pc
ON t. object_id = pc. object_id
AND ix.index_id = pc.index_id
WHERE ps.avg_fragmentation_in_percent > 10
AND ix.name IS NOT NULL
-- 上面语句是网上的,加了行数判断,也可以用页数量判断
and exists (
select * from sys.partitions where object_id = t. object_id and rows > 10000
/* 控制一下记录行数,因为小表的rebuild等会根据很多参数标准来判断是否要去重建。
网上搜索的判断因子:
生成查询计划的阀值
缓存机制,缓存的筛选,LRU算法
预读机制
checkpoint减少回滚距离
智能join判断
重编译
*/
)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值