做网站预算,淘宝客做网站教程,百度认证考试,微信网站开发设计我们都知道建索引是需要谨慎的#xff0c;当只有利大于弊的时候才适合建#xff0c;同时也知道建索引是需要维护成本的#xff0c;这个维护也就在于DML操作#xff0c;下面具体看看到底DML对索引都有哪些内幕。。。。一#xff1a;delete操作现在大家都已经知道索引是以B树… 我们都知道建索引是需要谨慎的当只有利大于弊的时候才适合建同时也知道建索引是需要维护成本的这个维护也就在于DML操作下面具体看看到底DML对索引都有哪些内幕。。。。一delete操作现在大家都已经知道索引是以B树的形式存在既然是B树就要给大家展示一下叶子节点和分支结点先准备点测试数据如下代码
CREATE TABLE Person(ID INT,NAME CHAR(200))
CREATE INDEX idx_Name ON Person(NAME)DECLARE ch AS INT65
WHILE ch122
BEGININSERT INTO dbo.Person(ID,NAME)VALUES(ch,REPLICATE(CHAR(ch),200))SET chch1
END
1. 叶子结点的变化从上面的图中大概可以看到当我插入完毕后4个索引数据页就出来了其中PID200的为分支数据页其他三个为叶子节点数据页编号分别为175,201,202然后我就挑选第二个叶子节点数据页201号看看里面的数据是啥样的。从数据页中可以看到在201号数据页中有18个槽位当然除了通过槽位看记录条数之外你还可以通过Pageheader中的m_slotCnt来观察记 录个数如下图接下来大家再看看slot0槽位的内容是啥样如下代码
0000000000000000: 16484848 48484848 48484848 48484848 †.HHHHHHHHHHHHHHH
0000000000000010: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000020: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000030: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000040: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000050: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000060: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000070: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000080: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000090: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000A0: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000B0: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000C0: 48484848 48484848 48970000 00010007 †HHHHHHHHH.......
00000000000000D0: 00020000 ††††††††††††††††††††††††††††....
看到内容之后我们把这条记录删掉然后快速的观察数据页的变化很有意思的。。。。如下图仔细观察上面的图你会看到m_slotCnt18。。。。你也看到m_ghostRecCnt1看这个名字你就知道是“幻象”的意思。。。正因为被标记为幻象是因为sqlserver的后台进程会在某个时候把数据正真的删除掉比如你过个几秒之后再查看就能看到真的被清除了。2. 分支节点的变化说完叶子节点然后我们继续看看分支节点通过前面的博文你应该知道在分支节点中是依次保存着排序后的每个叶子节点中的最小值刚好 我删除了第二个叶子节点的第一个值那这个值也正好保存在分支节点中下面一个问题来了我刚才删除了ID72的记录那这条记录还会在分支节点中保存吗不用太兴奋用数据说话继续查看200号数据页。可以看到分支节点是不会删除这条记录的。二insert操作索引都是按照索引列升序的当我insert的时候是不是需要给我插入到排序的指定位置呢比如说我刚才删除的HHH。。。数据这次我再insert的时候是不是需要给我插入到第二个数据页的slot0位置呢下面继续用数据说话。
INSERT INTO dbo.Person VALUES(72,REPLICATE(CHAR(72),200))
DBCC PAGE(Ctrip,1,201,1)Slot 0, Offset 0x101c, Length 212, DumpStyle BYTERecord Type INDEX_RECORD Record Attributes NULL_BITMAP Record Size 212Memory Dump 0x000000000FE5B01C0000000000000000: 16686868 68686868 68686868 68686868 †.hhhhhhhhhhhhhhh
0000000000000010: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000020: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000030: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000040: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000050: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000060: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000070: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000080: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
0000000000000090: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
00000000000000A0: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
00000000000000B0: 68686868 68686868 68686868 68686868 †hhhhhhhhhhhhhhhh
00000000000000C0: 68686868 68686868 68c10000 00010002 †hhhhhhhhh.......
00000000000000D0: 00020000 ††††††††††††††††††††††††††††....Slot 1, Offset 0x1f04, Length 212, DumpStyle BYTERecord Type INDEX_RECORD Record Attributes NULL_BITMAP Record Size 212Memory Dump 0x000000000FE5BF040000000000000000: 16484848 48484848 48484848 48484848 †.HHHHHHHHHHHHHHH
0000000000000010: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000020: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000030: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000040: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000050: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000060: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000070: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000080: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
0000000000000090: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000A0: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000B0: 48484848 48484848 48484848 48484848 †HHHHHHHHHHHHHHHH
00000000000000C0: 48484848 48484848 48c10000 00010015 †HHHHHHHHH.......
00000000000000D0: 00020000 ††††††††††††††††††††††††††††....
从上面可以看到当我再次把删除的”H插入到数据页的时候发现“H”在201号数据页的slot1位置了有人就奇怪了为什么不在slot0 的仔细想想确实是这么一个道理那就是sql是不区别大小写的“H”和“h”对sqlserver来说都是一样这里还有一个问题就是数据页分裂比如说当你insert的数据页已满那这时候该怎么办呢sqlserver的手段就是数据页分裂将满页的一半数据导出到新分配的数据页同样我也可以做个例子。
CREATE TABLE Person(ID INT,NAME CHAR(5) DEFAULT xxxxx)
CREATE INDEX idx_Name ON Person(NAME)DECLARE i as int1
WHILE i801
BEGININSERT INTO dbo.Person(ID) VALUES(i)SET ii1
END
接下来我导出126号数据页的记录可以看到它的范围是1-449如下图下面我要做的事情就是插入一个ID在1-449范围的一条记录这样的话就会造成数据页分裂了对不对。可以看到现在多了一个192号数据页是不是很有意思哈哈~~ 然后我就非常好奇的再次导出126192号数据页看看数据是不是只剩 一半啦~~~三update操作如果你看懂了上面的insert和delete那么update就是这两个操作的组合也没什么好说的。好了夜深了洗洗睡了~如您有更多问题与我互动扫描下方进来吧~