码迷,mamicode.com
首页 > 其他好文 > 详细

索引重整原理

时间:2015-04-29 23:09:30      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

碎片重整是为尽量保持索引联机可用的同时从索引的叶级别消除逻辑碎片而设计的。当对索引碎片整理的时候,SQL Server 会在索引的B-树结构上获取一个意向共享锁。只有在分页被实际操作时才在这些个别分页上占有排他分页锁。

 
2005 重整通过 alter index 命令发起的。移除碎片命令的一般格式如下:
alter index { index_name | all }
  on <object>
  reorganize
      [ partition = partition_number ]
      [ with ( LOB_COMPACTION = { ON | OFF } ) ]
 
它支持已分区索引(partition index),因此可以选择只对某个特定分区进行碎片重整。默认情况下是对所有分区进行碎片整理。如果索引并不是分区的话,指定一个分区号会产生错误。另外一个新的功能是允许用户控制 LOB 数据是否受到磁盘重整的影响。
 
索引的碎片重整需要两个阶段。第一个是压缩阶段,而第二个阶段是对数据分页进行实际的重新排列以使得分页的逻辑顺序和物理顺序一致
 
如前所述,每个索引在创建史都指定了填充因子(fillfactor)。最初的填充因子的数值存储在索引的元数据中,因此当需要碎片重整时,SQL Server 可以检查这个数值。在碎片整理期间,如果初始的填充因子大于当前填充因子的话,SQL Server 会试图复原初始的填充因子。碎片重整有意压缩数据,而且这可以通过每页放置更多记录以增加每个分页的充满程度来完成。SQL Server 可能在碎片整理后从索引中移除分页并作为结束。如果当前的填充因子大于初始的填充因子,SQL Server 就必须增加更多分页来复原这个初始值,而这在碎片重整的时是不会发生的。压缩算法(按照逻辑顺序)检查邻接的分页以判断是否有空间可以将第二页上的数据移至第一个分页上。SQL Server 2005 通过检查八个逻辑上连续分页的滑动窗口使这个过程变得更有效率。该算法判断是否可以将来自八个分页中的任意一些分页上的记录移至其他分页,从而完全清空一个分区
 
如前所述,SQL Server 2005 还提供了压缩 LOB 分页的选项。其默认值为 ON。对一个指定的聚集索引进行重组会在压缩叶子分页之前压缩所有包含于该聚集索引的 LOB 字段。对非聚集索引进行重组会压缩索引中的那些非键值(已包含)的LOB字段。
 
SQL Server 2000 中,用户能够压缩数据表中的 LOB 字段的唯一方法是卸载并重载 LOB 数据。2005 中的 LOB 压缩会寻找低密度的扩展——那些小于 75%利用率的扩展。它将分区从这些低密度的单一盘区(uniform extents)中移出,并将这些移出的分页放到其他已分配给 LOB 分配单元统一扩展的可用空间中去。这个功能使磁盘空间的利用得到大幅提升(这些空间在低密度 LOB 扩展中是浪费的)。在压缩阶段和下一阶段的过程中都不会分配新的扩展。
 
重组操作的第二个阶段为了使数据的逻辑顺序和物理顺序保持一致,实际上将数据移至新的分页的行内分配单元中。索引仍然保持联机状态,因为 SQL Server 在类似于冒泡排序的操作中每次只处理两个分页下面的例子是实际重组过程的一个简化。考虑在 datetime 数据字段上的一个索引。星期一的数据在逻辑上排在星期二的数据之前,星期二的数据排在星期三的数据之前,星期三的数据排在星期四之前。但是,如果星期一的数据存放在分页 88 上,星期二的数据在分页 50 上,星期三的数据在分页 100 上,而星期四的数据在分页 77 上,这使得物理顺序和逻辑顺序之间并不匹配,因而产生逻辑碎片。在对索引进行碎片整理时,SQL Server 确定了属于叶级别的首个物理分页(在本例中是分页 50)以及叶级别中的首个逻辑分页(分页 88,持有星期一的数据),并以一个额外的新分页作为临时存储区将这两个分页上的数据进行交互。交互以后,首个逻辑分页——持有星期一数据的分页现在是物理分页中页号最小的那个分页——分页 50。在每次交换分页以后,SQL Server 会释放所有使用到的锁和闩,并保存最后移动在分页上的键。该算法的下一次迭代使用保存的键来寻找下一个逻辑分页——星期二的数据,目前在分页 88 上。下一个物理分页是 77,存放着星期四的数据。因此,通过又一次的交换使分页 77 保存星期二的数据而分页 88 保存星期四的数据。这个过程继续进行直到无需再做任何交换为止。注意混合扩展(mixed extents)上的分页是无法进行碎片整理的
 
由于分页交换的数量似乎与乱序分页的数量成正比,读者可能很想知道如果在没有碎片或者只有很少碎片的情况下发起一次碎片重整重整操作是否有任何损害。在大多数情况下,如果没有碎片。碎片整理不会交换任何分页。但是,会发生这样一直尴尬的场景:很少的碎片可能需要相当大的工作量来完成重建。设想一个具有上千分页的索引,除了最后一个分页以外,其他所有分页都在逻辑上保持有序。按照逻辑顺序,第一个分页的数据(譬如,2000年1月1日)保存在分页101上,下一个(2000年1月2日)在分页102上,再下一个在分页 103 上,依此类推。但是最后一个逻辑分页的数据 2006 年 1月 31日存放在分页100上。对于一个 1000页的数据表来说,碎片的报告值只有 0.1%,因为1000个分页中只有一个处于乱序。如果还是决定对只有如此低的碎片百分比的索引进行重整的话,碎片整理算法会将分页 100 与 101 交换,然后交换101和102,接着交换102和103,直到表中的最后一个日期保存到最后一个分页为止。尽管可能只有一个分页处于乱序,但是不得不进行一千次交换来完成碎片重整。这里强烈建议在了解数据的碎片程度并决定需要无碎片数据以达到最佳性能之前,不要轻易地对数据进行碎片整理。
 
用户必须注意使用 reorganize 选项的一些限制。当然,如果索引被禁用是无法进行碎片重整的。同样,由于移除碎片的过程需要在个别分页上进行操作,如果试图对一个 allow_page_locks 选项设为 OFF 的索引进行碎片整理的话会收到一个错误。如果有并发的联机索引建在同一个索引之上或者别的进程正在并发地同一个索引行重组的话,就无法对当前索引进行重组了
 
可以通过 sys.dm_exec_requests 动态管理视图的 complete_percentage 和 estimated_completion_time 字段来观察每个索引的重组进程。
complete_percentage 字段的值显示了索引重组的完成度(百分比),estimated_completion_time 字段的值则显示了预计完成剩余索引重组锁的需要的时间(单位:毫秒)。如果在同一个语句中对多个索引进行重组,可以看到这些数值在每个索引轮流进行碎片整理时会上下浮动。
 
 
 
 
 
 

索引重整原理

标签:

原文地址:http://www.cnblogs.com/LvanHades/p/4467280.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!