Sql Server之旅——第七站 复合索引和include索引到底有多大区别?

索引和锁,这两个主题对我们开发工程师来说,非常的重要。。。只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的索引都是单列索引。。。当然数据库不可能只认单列索引,还有我这篇的复合索引,说到复合索引,可能熟悉的人又会说到include,那这两个索引到底有什么区别呢? 我也是菜鸟一枚。。。所以下面的也是我的个人见解。。。

一:从数据页角度看问题

1. 做两个表,插入两条数据,在test1上做复合索引,在test2上做include索引,如下图:


-- 在test1表中插入2条记录
CREATE TABLE test1(ID int,Name CHAR(5),Email CHAR(10))
INSERT INTO test1 VALUES(1,'aaaaa','111@qq.com')
INSERT INTO test1 VALUES(2,'bbbbb','222@qq.com')
CREATE INDEX idx_test1 ON dbo.test1(Name,Email)-- 在test2表中插入2条记录
CREATE TABLE test2(ID int,Name CHAR(5),Email CHAR(10))
INSERT INTO test2 VALUES(1,'aaaaa','111@qq.com')
INSERT INTO test2 VALUES(2,'bbbbb','222@qq.com')
CREATE INDEX idx_test2 ON dbo.test2(Name) INCLUDE(Email)

2. 然后通过DBCC 命令查看数据页记录

<1> 先来看看test1表中各个槽位的信息


DBCC TRACEON(2588,3604)
DBCC IND(Ctrip,test1,-1)
DBCC PAGE(Ctrip,1,194,1)Slot 0, Offset 0x60, Length 27, DumpStyle BYTERecord Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27Memory Dump @0x000000000FB0A0600000000000000000:   16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com
0000000000000010:   c0000000 01000000 030000†††††††††††††...........Slot 1, Offset 0x7b, Length 27, DumpStyle BYTERecord Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27Memory Dump @0x000000000FB0A07B0000000000000000:   16626262 62623232 32407171 2e636f6d †.bbbbb222@qq.com
0000000000000010:   c0000000 01000100 030000†††††††††††††...........OFFSET TABLE:Row - Offset
1 (0x1) - 123 (0x7b)
0 (0x0) - 96 (0x60)

<2> 再来看看test2表中各个槽位信息


DBCC TRACEON(2588,3604)
DBCC IND(Ctrip,test2,-1)
DBCC PAGE(Ctrip,1,207,1)Slot 0, Offset 0x60, Length 27, DumpStyle BYTERecord Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27Memory Dump @0x000000000DFCA0600000000000000000:   16616161 6161c400 00000100 00003131 †.aaaaa........11
0000000000000010:   31407171 2e636f6d 030000†††††††††††††1@qq.com...Slot 1, Offset 0x7b, Length 27, DumpStyle BYTERecord Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27Memory Dump @0x000000000DFCA07B0000000000000000:   16626262 6262c400 00000100 01003232 †.bbbbb........22
0000000000000010:   32407171 2e636f6d 030000†††††††††††††2@qq.com...OFFSET TABLE:Row - Offset
1 (0x1) - 123 (0x7b)
0 (0x0) - 96 (0x60)

<3> 从test1和test2的数据页来看,都是有两个slot槽位,然后我们把test1和test2的slot0槽位拿出来对比下,是不是就知道两者大概有什么区别了。

test1のslot0


0000000000000000:   16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com 
0000000000000010:   c0000000 01000000 030000†††††††††††††...........

test2のslot0


0000000000000000:   16616161 6161c400 00000100 00003131 †.aaaaa........11 
0000000000000010:   31407171 2e636f6d 030000†††††††††††††1@qq.com...

下面我仔细解剖下两表中的slot内容:

  • 16 6161616161 3131314071712e636f6d c0000000 0100 0000 0300 00

16: 这个是索引记录的系统头数据。

6161616161: 转换成十进制就是9797979797,也就是字符的aaaaa。

3131314071712e636f6d: 这个我想你也懂,也就是111@qq.com。

c000000010000000: 因为我们是堆表,所以这个就是表的RowID,转化为十进制就是:192:1:0。

0300:这个表示表中的记录数,也就是3条记录。

如果你对上面的讲解明白了,那我们继续看看test2のslot0,如果你仔细的话,你会看到在test2中,111qq.com是在记录的最后。。。那这说明什么问题呢???如果你对记录比较熟悉的话,你就知道,其实记录中的变长字段值一般都是放在记录的尾部。。。好处就是可以做到“行溢出”。也就是可以超过索引的900长度限制。。。而复合索引却无法做到。。。如果你不信我可以做个例子,将name和email的长度设为定长500。

而include索引却可以顺利通过。。。。。

夜深了,不准备继续说了。。。下一篇继续扯下复合索引到底都能带来哪些好处。

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

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

相关文章

Go中new和make的区别

Go中new和make的区别 变量声明 当我们声明变量时可以使用var关键字&#xff0c;当不指定变量的默认值时&#xff0c;这些变量的默认值就是他们的零值&#xff0c;比如int的默认值为0&#xff0c;string的默认值为""&#xff0c;引用类型的零值为nil。 但是当我们在…

POJ 3159 Candies(差分约束+SPAF)

题意&#xff1a; 给n个小朋友分发糖果&#xff0c;但小朋友们之间有嫉妒心。接下来m行&#xff0c;每行三个数&#xff0c;分别表示小朋友A希望B得到的糖果不能比他多x个。要求你计算在满足所有小朋友的条件的情况下最多需要准备多少颗糖。 题目&#xff1a; During the ki…

掌握了Docker Layer Caching才敢自称精通Dockerfile

长话短说&#xff1a;本次原创将向您展示在Docker中使用Layer Cache以加快镜像构建。“这个话题的初衷在于&#xff1a;应用打包过程是很慢的(下载并安装框架&第三方依赖包、生成assets)&#xff0c;这个过程在Docker中也不能避免。About Layer Caching in DockerDocker使…

Go unsafe Pointer

Go unsafe Pointer Go被设计为一种强类型的静态语言&#xff0c;强类型意味着类型一旦确定就无法更改&#xff0c;静态意味着类型检查在运行前就做了。 指针类型转换 为了安全考虑&#xff0c;两个不同类型的指针不能相互转换&#xff0c;例如&#xff1a; package mainfun…

How Many Answers Are Wrong HDU - 3038(带权并查集)

题意&#xff1a; TT写一个数列&#xff0c;现在TT会选择一个区间&#xff0c;然后让FF计算这个区间里面所有数的和&#xff0c;FF准备捉弄一下TT&#xff0c;有时候她会故意计算出来一个错的答案&#xff0c;当然TT也比较聪明&#xff0c;他会发现这个答案跟以前的答案会有冲…

ASP.NET Core on K8s学习之旅(14)Ingress灰度发布

【云原生】| 作者/Edison Zhou这是恰童鞋骚年的第236篇原创文章上一篇介绍了Ingress的基本概念和Nginx Ingress的基本配置和使用&#xff0c;然后我还录了一个快速分享小视频介绍了一下蓝绿发布和灰度发布策略的基本概念&#xff0c;本篇介绍一下如何实战使用Nginx Ingress实现…

[汇编语言]实验:应用更灵活的寻址方式来定位内存地址

实验内容: &#xff08;1&#xff09;将datasg段中每个单词的头一个字母改成大写字母。 datasg段中的数据为: &#xff08;2&#xff09; 将datasg段中每个单词的字母改成大写字母。 datasg段中的数据为: ibm dec dos vax …

Redundant Paths POJ - 3177(tarjan+边双连通分量)

题意&#xff1a; 有n个牧场&#xff0c;要求从一个牧场到另一个牧场&#xff0c;要求至少要有2条独立的路可以走。现已有m条路&#xff0c;求至少要新建多少条路&#xff0c;使得任何两个牧场之间至少有两条独立的路。两条独立的路是指&#xff1a;没有公共边的路&#xff0c…

Slice的本质

Slice的本质 我们先看下面的代码&#xff0c;看看它的输出是什么&#xff1a; package mainimport "fmt"type Slice []intfunc (A Slice) Append(value int) {A append(A, value) } func main() {mSlice : make(Slice, 10, 20)mSlice.Append(5)fmt.Println(mSlice…

你需要了解操作系统发展历程

本文我们大概回顾计算机操作系统发展历程&#xff0c;这里不会记录关于操作系统的完整历史记录&#xff0c;只是记录那些里程碑事件&#xff0c;看看各位接触计算机时&#xff0c;操作系统发展正处于哪个年代起初没有操作系统&#xff0c;没有编程语言或编译器&#xff0c;甚至…

[汇编语言]实验:更灵活的寻址方式 -应用si和di

实验内容: &#xff08;1&#xff09; 用寄存器SI和DI实现将字符串‘welcome to masm!’ 复制到它后面的数据区中。 &#xff08;2&#xff09; 用[bx(si或di)idata]的方式&#xff0c;来使程序变得简洁。 &#xff08;1&#xff09; 代码如下: assume ds:datasg,cs:code…

http.ListenAndServe()到底做了什么?

参考&#xff1a;https://studygolang.com/articles/25849?frsidebar ​ http://blog.csdn.net/gophers 实现一个最简短的hello world服务器 package mainimport "net/http"func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Reque…

Strongly connected HDU - 4635(tarjan+强连通分量)

题意&#xff1a; 给一个简单有向图&#xff0c;让你加最多的边&#xff0c;使他还是一个简单有向图。 题目&#xff1a; Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a …

C++编程基础题训练

1.编写一个c风格的程序&#xff0c;用动态分配空间的方法计算Fibonacci数列的前20项并存储到动态分配的空间中 1.代码如下 #include <iostream> using namespace std;int main() {int *a new int[25];a[0] 0;a[1] 1;for (int i 2; i < 20; i){a[i] a[i - 1] a…

基于 abp vNext 和 .NET Core 开发博客项目 - 使用Redis缓存数据

上一篇文章完成了项目的全局异常处理和日志记录。在日志记录中使用的静态方法有人指出写法不是很优雅&#xff0c;遂优化一下上一篇中日志记录的方法&#xff0c;具体操作如下&#xff1a;在.ToolKits层中新建扩展方法Log4NetExtensions.cs。//Log4NetExtensions.cs using log4…

G - 水陆距离 HihoCoder - 1478(广搜+队列先进先出性质)

题目&#xff1a; 给定一个N x M的01矩阵&#xff0c;其中1表示陆地&#xff0c;0表示水域。对于每一个位置&#xff0c;求出它距离最近的水域的距离是多少。 矩阵中每个位置与它上下左右相邻的格子距离为1。 Input 第一行包含两个整数&#xff0c;N和M。 以下N行每行M个0…

第一讲 工作区和GOPATH

此为 《极客时间&Go语言核心36讲》 个人笔记&#xff0c;具体课程详见极客时间官网。 Table of Contents generated with DocToc 第一讲 工作区和GOPATH 1. 环境变量配置2. 配置GOPATH的意义 2.1 Go语言源码的组织方式2.2 源码安装后的结果&#xff08;归档文件、可执行文…

C++重载运算符小结与注意点

重载运算符需注意: 1.重载运算符时容易忘记写返回值。 2.重载赋值运算符时&#xff0c;记得加const&#xff0c;因为赋值操作必须是固定的右值。 3重载时&#xff0c;写在类中的只能有一个参数(实际有两个参数&#xff0c;另外一个是this指针&#xff0c;我们看不见而已)&am…