关于TF 1118的一些误解

关于TF 1118的一些误解

原文:Misconceptionsaround TF 1118

原文地址:http://www.sqlskills.com/BLOGS/PAUL/post/Misconceptions-around-TF-1118.aspx

最近有一些有关SQL SERVER 2008下跟踪标志(Trace Flag)1118的一些误解。该跟踪标志可以将tempdb中单次分配前8页变成一次分配1个区(8页)。这可以缓解tempdb下由于大量的小临时表的创建/删除而造成的分配位图竞争。

有下面几点误解,我将依次说明。然后我将证明在SQL SERVER 2008下该跟踪标志仍然有效。

1)为什么在2000下总是需要这个跟踪标志?在SQL 2000中,无论何时创建一个临时表并插入一行数据,系统都会分配一个IAM页和一个数据页。这两页都是从混合区中单页分配的(见Inside The Storage Engine: Anatomy of an extent formore info译文)。就是说必须要存取一个分配位图页SGAM页和一个PFS页(见Inside The Storage Engine: GAM, SGAM, PFS and otherallocation maps译文)。

当有无数的小临时表被创建,这就意味着所有的线程都需要存取数据文件的第一个SGAM页和第一个PFS页,这将导致在这两页上的闩竞争。当临时表被删除,它所分配的各种页也需要释放,这又需要存取并修改PFS页,可能还有SGAM页。

有两种方法可以缓解这个问题。第一种方法是为tempdb创建多个数据文件——这将在多个分配位图(从多个文件)之间平摊闩竞争,从而减少竞争。一般的原则是一个CPU内核对应一个文件。另一种方法就是打开TF1118,这将使得临时表的前8页也从统一区中分配。就是说从GAM中分配一个区,而不是单次分配8个页(也就会8次存取SGAM页)。区中的页先被保留起来,然后再根据需要单个页地分配。这也将减少竞争(见KB328551)。

2)什么是保留和分配?当为一个表分配了一个区,区上的8个页并不是立刻被分配的。分配一个区表示它上面的8个页被保留,以后只能由这个表使用。这些页可以根据需要单个分配,但是其他表不能使用这些页。这就是为什么这种区被称为“统一区”。你可以通过sp_spaceused输出保留页和已分配页的数目。

3)为什么在2005和2008不再如此需要这个跟踪标志了?在SQL SERVER 2005中,我们小组修改了tempdb的分配系统,以减少可能的竞争。现在出现了一个临时表的缓存。当一个新临时表从冷系统(即刚启动)中创建,系统会使用和SQL 2000一样的分配机制。不过当删除这个表时,系统并不像以前那样完全释放所有页,而是依然保留一个IAM页和一个数据页,这个临时表被放在一个特殊的缓存中。后面临时表的创建会查看是否可以从缓存中取出一个预创建的临时表,如果可以,就可以完全避免存取分配位图了。临时表缓存不是很大(我想是32个表),但是这仍将大大减少tempdb中的闩竞争。

4)在2005和2008中还有这个跟踪标志吗?是的,KB328551上说得很清楚:跟踪标志T1118在SQL SERVER 2005和2008中依然有效。但是,如果你运行在SQL SERVER 2005和2008上,并不需要使用任何补丁(译注:言下之意是2000下需要补丁)。

仅仅为了确保(就像我总是必须说得非常绝对),我向我的好友Ryan Stonecipher进行了求证。他是开发小组的组长,他们小组拥有分配过程(和其他一些功能,如DBCC)的代码。他确认2008和2005下的代码是一样的。过会儿我也会证明这点的。

5)为什么在2005和2008中还要TF1118呢?TF1118在2005/2008下是和2000下功能是一样的。如果临时表的创建/删除量足够大,你还是会看到闩竞争的,因为临时表缓存并不足以完全缓解创建新临时表的需求。此时,使用跟踪标志将单页分配改成区分配(就跟2000下一摸一样)就能起作用了,当然也可以创建多个tempdb数据文件。

尽管还可以创建数据文件,但数目已经变了。原来那种在CPU内核数和tempdb文件数(如果有闩竞争的话)之间的1:1关系已经不再需要了——现在SQL 小组的建议是数据文件数是CPU内核数的1/4到1/2。SQL CAT小组也发现在2005和2008下,不管有多少CPU内核,超过8个数据文件通常就不会带来什么性能提升了。注意:这是通常的情况。你的情况可以有所不同,所以不要发表评论说这是错误的,因为你的系统就是12个数据文件。因为这是通常情况,总是会有例外的。

6)为什么DBCC IND在跟踪标志开启后仍显示为两页呢?我听说有人对2008下的DBCC INDEX 输出产生困惑。创建一个单行的表会在DBCC输出中显示只分配了两页:一个IAM页和一个数据页。是的,这完全正确——因为确实只有两页被分配,但是数据页是从统一区而不是混合区中分配(IAM页总是从混合页中分配的)。

下面是SQL 2008下的证据:

SELECT@@VERSION;
GO

MicrosoftSQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)

首先在关闭跟踪标志的情况下创建一个临时表,然后通过第一个IAM页看看这个表分配了几页。我创建的表一行会超过8000个字节,这样插入两行就会非常清楚地看到分配了两页。

DBCC TRACEOFF (1118, -1);
GO

USEtempdb;
GO

CREATETABLE #temp (c1 INT IDENTITY, c2 CHAR (8000) DEFAULT 'a');
GO
INSERT INTO #temp DEFAULT VALUES;
GO 2

现在我用sp_AllocationMetadata脚本来看看第一个IAM页是什么。然后用DBCC PAGE来看看该IAM所跟踪的单页分配情况,看看分配了哪个统一区。

EXECsp_AllocationMetadata '#temp';
GO

ObjectName Index ID Alloc Unit ID Alloc Unit Type First Page Root Page First IAM Page
-------------- --------- -------------------- ---------------- --------------------- ---------------
#temp__<snip> 0 1152921505223016448 IN_ROW_DATA (1:158) (0:0) (1:199)

DBCCTRACEON (3604);
GO
DBCC PAGE ('tempdb', 1, 199, 3);
GO

<snip>

IAM:Single Page Allocations @0x4A35C08E

Slot 0= (1:158) Slot 1 = (1:200) Slot 2 = (0:0)
Slot 3 = (0:0) Slot 4 = (0:0) Slot 5 = (0:0)
Slot 6 = (0:0) Slot 7 = (0:0)


IAM: Extent Alloc Status Slot 1 @0x4A35C0C2

(1:0) -(1:1016) = NOT ALLOCATED

你可以从IAM页的部分输出很清楚地看出:有两个单页,但是没有统一区。这正是在没有开启TF1118的样子。

下面我要在开启TF1118情况下做同样的事情。

USEtempdb;
GO

DROPTABLE #temp;
GO

DBCC TRACEON (1118, -1);
GO

CREATETABLE #temp (c1 INT IDENTITY, c2 CHAR (8000) DEFAULT 'a');
GO
INSERT INTO #temp DEFAULT VALUES;
GO 2

EXECsp_AllocationMetadata '#temp';
GO

ObjectName Index ID Alloc Unit ID Alloc Unit Type First Page Root Page First IAM Page
-------------- --------- -------------------- ---------------- --------------- ------ ---------------
#temp__<snip> 0 1224979099301904384 IN_ROW_DATA (1:208) (0:0)(1:158)

DBCCTRACEON (3604);
GO
DBCC PAGE ('tempdb', 1, 158, 3);
GO

<snip>

IAM:Single Page Allocations @0x4A8FC08E

Slot 0= (0:0) Slot 1 = (0:0) Slot 2 = (0:0)
Slot 3 = (0:0) Slot 4 = (0:0) Slot 5 = (0:0)
Slot 6 = (0:0) Slot 7 = (0:0)


IAM: Extent Alloc Status Slot 1 @0x4A8FC0C2

(1:0) -(1:200) = NOT ALLOCATED
(1:208) - = ALLOCATED
(1:216) - (1:1016) = NOT ALLOCATED

现在你会清楚地看到:没有单页分配,但是有一个分配。这证明了TF1118做了SQL 2008下它应该做的。

下面我们使用DBCC IND来看看表:

DBCC IND ('tempdb', '#temp',-1);
GO

PageFID PagePID IAMFID IAMPID ObjectID IndexID
------- ----------- ------ ----------- ----------- -----------
1 158 NULL NULL 293576084 0
1 208 1 158 293576084 0
1 209 1 158 293576084 0

(为清楚起见,我已经删除了部分列)我们可以看到还是只列出两个数据页(1:208,1:209)和一个IAM页(1:158)——尽管一整个区已经分配给该临时表了, 但是实际上只有两个页被分配和使用——剩下的被该表所保留,只是显示为未分配。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值