Sql Server之旅——第九站 看看DML操作对索引的影响

 我们都知道建索引是需要谨慎的,当只有利大于弊的时候才适合建,同时也知道建索引是需要维护成本的,这个维护也就在于DML操作,下面具体看看到底DML对索引都有哪些内幕。。。。

一:delete操作

现在大家都已经知道索引是以B树的形式存在,既然是B树就要给大家展示一下叶子节点和分支结点,先准备点测试数据,如下代码:


CREATE TABLE Person(ID INT,NAME CHAR(200))
CREATE INDEX idx_Name ON Person(NAME)DECLARE @ch AS INT=65
WHILE @ch<=122
BEGININSERT INTO dbo.Person(ID,NAME)VALUES(@ch,REPLICATE(CHAR(@ch),200))SET @ch=@ch+1
END

1. 叶子结点的变化

从上面的图中大概可以看到,当我插入完毕后,4个索引数据页就出来了,其中PID=200的为分支数据页,其他三个为叶子节点数据页,编号分别为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_slotCnt=18。。。。你也看到m_ghostRecCnt=1,看这个名字你就知道是“幻象”的意思。。。正因为被标记为幻象,是因为sqlserver的后台进程会在某个时候把数据正真的删除掉,比如你过个几秒之后再查看就能看到真的被清除了。

2. 分支节点的变化

说完叶子节点,然后我们继续看看分支节点,通过前面的博文,你应该知道在分支节点中是依次保存着排序后的每个叶子节点中的最小值,刚好 我删除了第二个叶子节点的第一个值,那这个值也正好保存在分支节点中,下面一个问题来了,我刚才删除了ID=72的记录,那这条记录还会在分支节点中保存吗???不用太兴奋,用数据说话,继续查看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 int=1
WHILE @i<801
BEGININSERT INTO dbo.Person(ID) VALUES(@i)SET @i=@i+1
END

接下来,我导出126号数据页的记录,可以看到它的范围是1-449,如下图:

下面我要做的事情就是插入一个ID在1-449范围的一条记录,这样的话就会造成数据页分裂了,对不对。

可以看到,现在多了一个192号数据页,是不是很有意思,哈哈~~ 然后我就非常好奇的再次导出126,192号数据页,看看数据是不是只剩 一半啦~~~

三:update操作

如果你看懂了上面的insert和delete,那么update就是这两个操作的组合,也没什么好说的。

好了,夜深了,洗洗睡了~


如您有更多问题与我互动,扫描下方进来吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309540.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Java基础]反射获取成员方法并使用

代码如下: package ClassObjectPack01;import ClassObjectPack.Student;import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;public class ReflectDemo05 {public static void main(String[] args)…

副业刚需? 恐怕并不靠谱!

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份上一篇文章推了我的星球&#xff0c;两天时间就有接近200位读者加入。有「热心朋友」帮我计算了下&#xff1a;你这两天收入快2万啊&#xff0c;你这副业做的挺好啊。很不客气的说&#xff0c;如果写写公号&a…

[Java基础]Junit测试

Junit测试: 代码如下: package CalculatorPack;public class Calculator {public int add(int a,int b){return ab;}public int sub(int a,int b){return a-b;}}package CalculatorPack;import org.junit.Assert; import org.junit.Test;public class CalculatorTest {Testp…

15分钟为自己架设优雅如Github的代码仓库

前言Github大家都熟悉。除了开源的项目外&#xff0c;有时候&#xff0c;大家也会把自己或团队、公司的项目传到Github的私有仓库里&#xff0c;把Github当成自己的私人Git Server。但是&#xff0c;用Github会有一些问题&#xff1a;Github从国内访问不是很稳定&#xff0c;有…

Pseudoprime numbers POJ - 3641(快速幂+判素数)

题意&#xff1a; 给你两个数&#xff0c;p和a&#xff1b;满足两个条件&#xff1a; 1.p不是素数&#xff1b; 2.apa^{p}ap %pa; 满足则输出yes&#xff0c;反之输出no。 题目&#xff1a; Fermat’s theorem states that for any prime number p and for any integer a &g…

[Java基础]反射案列

pro.properties文件(该文件与ReflectTest01同处在同一个文件夹)&#xff1b; className domain.Person methodName eat代码如下: package domain;public class Student {public void sleep(){System.out.println("sleep...");} }package domain;public class Per…

[推荐]大量 Blazor 学习资源(三)

大量 Blazor 学习资源系列文章&#xff1a;[推荐]大量 Blazor 学习资源&#xff08;一&#xff09;[推荐]大量 Blazor 学习资源&#xff08;二&#xff09;这次主要内容有 Blazor 相关视频&#xff0c;因为本身视频是英文的&#xff0c;所以就保持原样了&#xff0c;描述没有翻…

基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二)

上一篇使用HtmlAgilityPack抓取壁纸数据成功将图片存入数据库&#xff0c;本篇继续来完成一个全网各大平台的热点新闻数据的抓取。同样的&#xff0c;可以先预览一下我个人博客中的成品&#xff1a;https://meowv.com/hot ????????????&#xff0c;和抓取壁纸的套路…

TechEmpower Web 框架性能第19轮测试结果正式发布,ASP.NET Core在主流框架中拔得头筹...

TechEmpower第19轮编程语言框架性能排行榜2020年5月28日正式发布,详见官方博客&#xff1a;https://www.techempower.com/blog/2020/05/28/framework-benchmarks-round-19/&#xff0c;TechEmpower基准测试有许多场景&#xff08;也称为测试类型&#xff09;&#xff0c;此次评…

[Java基础]JDK内置注解

示例代码如下: package annotation;SuppressWarnings("all") public class AnnoDemo2 {Overridepublic String toString(){return super.toString();}Deprecatedpublic void show(){//有缺陷}public void show1(){//替代show方法}public void demo(){show();}}

学了这么多年精益思想,居然不知道还有第八种浪费 | IDCF

价值和浪费“我是彻底的现场主义者。与其在领导办公室内冥思苦想&#xff0c;倒不如到生产现场的各个角落&#xff0c;直接获得第一手的生产信息和感受直接的刺激。”——大野耐一&#xff0c;丰田生产方式之父大野耐一提倡直接去现场工作&#xff0c;在那里才能看到价值与浪费…

41 sysfs 文件系统

前言 在 linux 中常见的文件系统 有很多, 如下 基于磁盘的文件系统, ext2, ext3, ext4, xfs, btrfs, jfs, ntfs 内存文件系统, procfs, sysfs, tmpfs, squashfs, debugfs 闪存文件系统, ubifs, jffs2, yaffs 文件系统这一套体系在 linux 有一层 vfs 抽象, 用户程序不用…

A Greeting from Qinhuangdao Gym - 102769A 2020ccpc秦皇岛分站赛

题意&#xff1a; 给你n个红球和m个蓝色球。然后以相等的概率随机选择了其中两个。选择两个红球的概率是多少&#xff1f; 题目&#xff1a; Welcome to the CCPC Qinhuangdao Site! Qinhuangdao is a beautiful coastal city full of charm, integrating historical herit…

Gartner:6个容器和Kubernetes策略的最佳实用技巧

导语采用容器和Kubernetes要求整个企业保持一致&#xff0c;不了解这些前期现实会导致一些非常严峻的后果。正文Gartner估计&#xff0c;到2022年&#xff0c;将有75&#xff05;的组织在生产中运行容器化应用程序。毫无疑问&#xff0c;Kubernetes已成为组织容器的流行方法。通…

测试人员未来的3条出路

大家好&#xff0c;我是Z哥。前两天有个做测试的小伙伴加我微信问我测试相关的一些事情。她自己是从学习毕业就开始进入到互联网行业做测试的&#xff0c;到现在三年工作经验。她现在都不太敢跳槽&#xff0c;因为觉得自己没有什么核心竞争力&#xff0c;平常就是点点鼠标&…

自定义值类型一定不要忘了重写Equals,否则性能和空间双双堪忧

一&#xff1a;背景1. 讲故事曾今在项目中发现有同事自定义结构体的时候&#xff0c;居然没有重写Equals方法&#xff0c;比如下面这段代码&#xff1a;static void Main(string[] args){var list Enumerable.Range(0, 1000).Select(m > new Point(m, m)).ToList();var ite…

使用 Windows Terminal 连接远程主机

使用 Windows Terminal 连接远程主机IntroWindows Terminal 是微软新推出来的一个全新的、流行的、功能强大的命令行终端工具。包含很多来社区呼声很高的特性&#xff0c;例如&#xff1a;多 Tab 支持、富文本、多语言支持、可配置、主题和样式&#xff0c;支持 emoji 和基于 G…