曲演杂坛--重建索引后,还使用混合分区么?(Are mixed pages removed by an index rebuild?)
原文来自:http://www.sqlskills.com/blogs/paul/mixed-pages-removed-index-rebuild/
在SQL SERVER 中,区是管理空间的基本单位,连续的8个页为一分区,分区可分为混合区和统一区(也叫独占区),混合区内存放一个或多个对象的数据,统一区只存放一个对象的数据。为提高空间的利用率,对于新表或索引,会先从混合区上分配页,当表或索引增长到 8 页时,将变成使用统一区进行后续分配。
让我们来测试下
首先,创建测试数据
- --====================================
- --创建测试表
- CREATE TABLE [MixedTest]
- (
- [c1] BIGINT IDENTITY ,
- [c2] CHAR(8000) DEFAULT 'a'
- );
- --=======================================
- --创建聚集索引
- CREATE CLUSTERED INDEX [MixedTest_CL]
- ON [MixedTest] ([c1]);
- SET NOCOUNT ON;
- GO
- --====================================
- --插入1000条数据
- INSERT INTO [MixedTest]
- DEFAULT VALUES;
- GO 1000
Paul 使用sp_AllocationMetadata来查看对象的IAM页,然后再使用DBCC PAGE 查看IAM页的数据,从而判断数据页所在分区时混合还是统一区。
sp_AllocationMetadata的CODE:
- /*============================================================================
- File: sp_AllocationMetadata.sql
- Summary: This script cracks the system tables to provide top-level
- metadata about a table or index
- SQL Server Versions: 2005 onwards
- ------------------------------------------------------------------------------
- Written by Paul S. Randal, SQLskills.com
- (c) 2014, SQLskills.com. All rights reserved.
- For more scripts and sample code, check out
- http://www.SQLskills.com
- You may alter this code for your own *non-commercial* purposes. You may
- republish altered code as long as you include this copyright and give due
- credit, but you must obtain prior permission before blogging this code.
- THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
- ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
- TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- PARTICULAR PURPOSE.
- ============================================================================*/
- USE [master];
- GO
- IF OBJECT_ID (N'sp_AllocationMetadata') IS NOT NULL
- DROP PROCEDURE [sp_AllocationMetadata];
- GO
- CREATE PROCEDURE [sp_AllocationMetadata]
- (
- @object SYSNAME = NULL
- )
- AS
- SELECT
- OBJECT_NAME ([sp].[object_id]) AS [Object Name],
- [sp].[index_id] AS [Index ID],
- [sa].[allocation_unit_id] AS [Alloc Unit ID],
- [sa].[type_desc] AS [Alloc Unit Type],
- '(' + CONVERT (VARCHAR (6),
- CONVERT (INT,
- SUBSTRING ([sa].[first_page], 6, 1) +
- SUBSTRING ([sa].[first_page], 5, 1))) +
- ':' + CONVERT (VARCHAR (20),
- CONVERT (INT,
- SUBSTRING ([sa].[first_page], 4, 1) +
- SUBSTRING ([sa].[first_page], 3, 1) +
- SUBSTRING ([sa].[first_page], 2, 1) +
- SUBSTRING ([sa].[first_page], 1, 1))) +
- ')' AS [First Page],
- '(' + CONVERT (VARCHAR (6),
- CONVERT (INT,
- SUBSTRING ([sa].[root_page], 6, 1) +
- SUBSTRING ([sa].[root_page], 5, 1))) +
- ':' + CONVERT (VARCHAR (20),
- CONVERT (INT,
- SUBSTRING ([sa].[root_page], 4, 1) +
- SUBSTRING ([sa].[root_page], 3, 1) +
- SUBSTRING ([sa].[root_page], 2, 1) +
- SUBSTRING ([sa].[root_page], 1, 1))) +
- ')' AS [Root Page],
- '(' + CONVERT (VARCHAR (6),
- CONVERT (INT,
- SUBSTRING ([sa].[first_iam_page], 6, 1) +
- SUBSTRING ([sa].[first_iam_page], 5, 1))) +
- ':' + CONVERT (VARCHAR (20),
- CONVERT (INT,
- SUBSTRING ([sa].[first_iam_page], 4, 1) +
- SUBSTRING ([sa].[first_iam_page], 3, 1) +
- SUBSTRING ([sa].[first_iam_page], 2, 1) +
- SUBSTRING ([sa].[first_iam_page], 1, 1))) +
- ')' AS [First IAM Page]
- FROM
- sys.system_internals_allocation_units AS [sa],
- sys.partitions AS [sp]
- WHERE
- [sa].[container_id] = [sp].[partition_id]
- AND [sp].[object_id] =
- (CASE WHEN (@object IS NULL)
- THEN [sp].[object_id]
- ELSE OBJECT_ID (@object)
- END);
- GO
- EXEC sys.sp_MS_marksystemobject [sp_AllocationMetadata];
- GO
- --USE [AdventureWorks];
- --GO
- --EXEC [sp_AllocationMetadata] N'HumanResources.Employee';
- --GO
个人更喜欢使用DBCC EXENTINFO来查看
--================================================================================
- --===========================
- --插入数据后查看
- DBCC EXTENTINFO('TestDB','MixedTest')
PS:注意上面8个数的Ext_Size为1,代表使用混合区
--================================================================================
- --===================================
- --在线重建索引后查看
- ALTER INDEX [MixedTest_CL]
- ON [MixedTest] REBUILD
- WITH(ONLINE=ON)
- DBCC EXTENTINFO('TestDB','MixedTest')
对比第一次的数据页ID,会发现重建后的索引,使用新的数据页,但是仍会为表分配混合区。
--================================================================================
- --===================================
- --脱机重建索引后查看
- ALTER INDEX [MixedTest_CL]
- ON [MixedTest] REBUILD
- WITH(ONLINE=OFF)
- DBCC EXTENTINFO('TestDB','MixedTest')
在脱机重建索引情况下,仍会为表分配混合区。
--=========================================================================
使用DROP_EXISTING=ON选项创建索引
- --===========================
- --使用DROP_EXISTING=ON选项创建索引
- CREATE CLUSTERED INDEX [MixedTest_CL]
- ON [MixedTest] ([c1])
- WITH(DROP_EXISTING=ON );
- DBCC EXTENTINFO('TestDB','MixedTest')
使用DROP_EXISTING=ON选项创建索引,仍会为表分配混合区。
--================================================================================
- --===========================
- --删除再创建索引
- DROP INDEX [MixedTest_CL]
- ON [MixedTest]
- GO
- CREATE CLUSTERED INDEX [MixedTest_CL]
- ON [MixedTest] ([c1])
- GO
- DBCC EXTENTINFO('TestDB','MixedTest')
删除再创建索引,仍会为表分配混合区。
--================================================================================
- --===================================
- --启用TF1118后,脱机重建索引后查看
- DBCC TRACEON(1118,-1)
- ALTER INDEX [MixedTest_CL]
- ON [MixedTest] REBUILD
- WITH(ONLINE=OFF)
- DBCC EXTENTINFO('TestDB','MixedTest')
在开启1118后,不再为对象分配混合区
--===============================================================================
部分同学会疑惑,为什么不一定总是8个页位于混合区中,个人理解是最开始存到到混合区的8个页,在后面的索引操作中,发生了数据页合并和移动等情况,因此导致原来在混合区的数据页被回收或移动到其他统一区上,因此导致存在混合区的数据页小于8个
Paul的原文如下:
there are only 7 mixed pages in the singe-page slot array above. What happened? The answer is that the offline index rebuild ran in parallel, with each thread building a partial index, and then these are stitched together. The ‘stitching together’ operation will cause some of the non-leaf index pages to be deallocated as their contents are merged together. This explains the deallocated page that was originally tracked by entry 3 in the slot array.
--===============================================================================
总结:在不开启1118条件下,无论是脱机还是联机,还是删除重建,无论是多线程还是单线程,实现各部相同,但都会为新表和索引分配混合区上的页。
--===============================================================================
问题1 :在MSDN上有“如果对现有表创建索引,并且该表包含的行足以在索引中生成 8 页,则对该索引的所有分配都使用统一区进行。”
但是经过测试,发现仍会分配混合区。
MSDN连接:http://msdn.microsoft.com/zh-cn/library/ms190969(v=sql.105).aspx
--==============================================================================
各位大师,猩猩,妹子来啦,此次该有掌声
曲演杂坛--重建索引后,还使用混合分区么?(Are mixed pages removed by an index rebuild?)的更多相关文章
- 曲演杂坛--一条DELETE引发的思考
原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...
- 曲演杂坛--使用CTE时踩的小坑:No Join Predicate
在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...
- 曲演杂坛--使用ALTER TABLE修改字段类型的吐血教训
--===================================================================== 事件起因:开发发现有表插入数据失败,查看后发现INT类型 ...
- 曲演杂坛--蛋疼的ROW_NUMBER函数
使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大 ...
- 曲演杂坛--当ROW_NUMBER遇到TOP
值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...
- 曲演杂坛--特殊字符/生僻字与varchar
对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...
- 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?
很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...
- 曲演杂坛--HASH的一点理解
HASH,百度百科上做如下定义: Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列 ...
- 曲演杂坛--EXISTS语句
通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...
随机推荐
- 百度BAE部署微信开发环境
这里会弹出一个SVN的账户和密码,这个账户和密码就是你百度的账户和密码 将项目导出WAR包到SVN的客户端目录里面 然后右键SVN Commit提交代码 部署列表有新版本 快捷发布 tocken认证失 ...
- 一些常用的c++系统函数
数学<cmath><math.h>: 1 三角函数 double sin (double); double cos (double); double tan (double); ...
- js字符串解析成数字
parseInt() 先把参数转换成字符串:左边有连续的数字则返回数值,若没有则返回NaN. console.log('parseInt(null)',parseInt(null)); // NaN ...
- IDEA 工具下导出文件及文件的目录结构插件
idea导出增量补丁插件 有时候需要导出IDEA的文件目录结构,即导出 指定修改后的JAVA文件编译后的CLASS .或者是修改过的jsp.配置文件等, 装载此插件,即可以完成导出文件 及文件的目 ...
- mvc 封装控件使用mvcpager
具体使用如下: 前台部分: @RenderPage("~/Views/Controls/_Pagebar.cshtml", new PageBar { pageIndex = Mo ...
- mysql简单实现查询结果添加序列号的方法
方法1: SELECT @rownum :=@rownum + 1 AS rownum, t.* FROM integral_system_user t, (SELECT @rownum := 0) ...
- BZOJ 1211[HNOI2004]树的计数 - prufer数列
描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...
- 前后台交互(打开前端页面,不传递任何数据,发送ajax请求)
1.打开前端,不传递任何数据 <script src="./jquery.min.js"></script> <script> $(docume ...
- [Git]Git的常用命令
Update: git status git diff wq git commit -am "why update files" git push Add: git add . g ...
- winsock select 学习代码(2)
之前文章的改进版 服务器仅仅接受客户端发送的字符串并显示 客户端可以调节发送数目 但是不能超过64 // SelectServer.cpp : 定义控制台应用程序的入口点. // #include & ...