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

  周末终于搬进出租房了,装了宽带。。。。才发现没网的日子。。。那是一个怎样的与世隔绝呀。。。再也受不了那样的日子了。。。。好了,既然网

安上去了,还得继续我的这个系列。

  索引和锁,这两个主题对我们开发工程师来说,非常的重要。。。只有理解了这两个主题,我们才能写出高质量的sql语句,在之前的博客中,我所说的

索引都是单列索引。。。当然数据库不可能只认单列索引,还有我这篇的复合索引,说到复合索引,可能熟悉的人又会说到include索引,那这两个索引到底

有什么区别呢,当然我也是菜鸟一枚。。。所以下面的也是我的个人见解。。。

一:从数据页角度看问题

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

 1 -- 在test1表中插入2条记录
 2 CREATE TABLE test1(ID int,Name CHAR(5),Email CHAR(10))
 3 INSERT INTO test1 VALUES(1,‘aaaaa‘,‘[email protected]‘)
 4 INSERT INTO test1 VALUES(2,‘bbbbb‘,‘[email protected]‘)
 5 CREATE INDEX idx_test1 ON dbo.test1(Name,Email)
 6
 7 -- 在test2表中插入2条记录
 8 CREATE TABLE test2(ID int,Name CHAR(5),Email CHAR(10))
 9 INSERT INTO test2 VALUES(1,‘aaaaa‘,‘[email protected]‘)
10 INSERT INTO test2 VALUES(2,‘bbbbb‘,‘[email protected]‘)
11 CREATE INDEX idx_test2 ON dbo.test2(Name) INCLUDE(Email)

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

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

1 DBCC TRACEON(2588,3604)
2 DBCC IND(Ctrip,test1,-1)
3 DBCC PAGE(Ctrip,1,194,1) 
 1 Slot 0, Offset 0x60, Length 27, DumpStyle BYTE
 2
 3 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
 4
 5 Memory Dump @0x000000000FB0A060
 6
 7 0000000000000000:   16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com
 8 0000000000000010:   c0000000 01000000 030000†††††††††††††...........
 9
10 Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE
11
12 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
13
14 Memory Dump @0x000000000FB0A07B
15
16 0000000000000000:   16626262 62623232 32407171 2e636f6d †.bbbbb222@qq.com
17 0000000000000010:   c0000000 01000100 030000†††††††††††††...........
18
19 OFFSET TABLE:
20
21 Row - Offset
22 1 (0x1) - 123 (0x7b)
23 0 (0x0) - 96 (0x60)            

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

1 DBCC TRACEON(2588,3604)
2 DBCC IND(Ctrip,test2,-1)
3 DBCC PAGE(Ctrip,1,207,1)
 1 Slot 0, Offset 0x60, Length 27, DumpStyle BYTE
 2
 3 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
 4
 5 Memory Dump @0x000000000DFCA060
 6
 7 0000000000000000:   16616161 6161c400 00000100 00003131 †.aaaaa........11
 8 0000000000000010:   31407171 2e636f6d 030000†††††††††††††1@qq.com...
 9
10 Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE
11
12 Record Type = INDEX_RECORD           Record Attributes =  NULL_BITMAP     Record Size = 27
13
14 Memory Dump @0x000000000DFCA07B
15
16 0000000000000000:   16626262 6262c400 00000100 01003232 †.bbbbb........22
17 0000000000000010:   32407171 2e636f6d 030000†††††††††††††2@qq.com...
18
19 OFFSET TABLE:
20
21 Row - Offset
22 1 (0x1) - 123 (0x7b)
23 0 (0x0) - 96 (0x60) 

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

test1のslot0

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

test2のslot0

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

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

16   6161616161   3131314071712e636f6d  c0000000 0100 0000  0300    00

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

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

3131314071712e636f6d:  这个我想你也懂,也就是[email protected]。

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

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

如果你对上面的讲解明白了,那我们继续看看test2のslot0,如果你仔细的话,你会看到在test2中,111qq.com是在记录的最后。。。那这说明什

么问题呢???如果你对记录比较熟悉的话,你就知道,其实记录中的变长字段值一般都是放在记录的尾部。。。好处就是可以做到“行溢出”。也就是

可以超过索引的900长度限制。。。而复合索引却无法做到。。。如果你不信我可以做个例子,将name和email的长度设为定长500。

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

这几天上海特别冷,打字都打着手哆嗦。。。不准备继续说了。。。下一篇继续扯下复合索引到底都能带来哪些好处。

时间: 2024-12-23 22:40:26

Sql Server之旅——第八站 复合索引和include索引到底有多大区别?的相关文章

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

我们都知道建索引是需要谨慎的,当只有利大于弊的时候才适合建,我们也知道建索引是需要维护成本的,这个维护也就在于DML操作了, 下面我们具体看看到底DML对索引都有哪些内幕.... 一:delete操作 现在我们已经知道,索引都是以B树的形式存在的,既然是B树,我们就要看看他们的叶子节点和分支结点,先准备点测试数据,如下图: CREATE TABLE Person(ID INT,NAME CHAR(200)) CREATE INDEX idx_Name ON Person(NAME) DECLAR

Sql Server之旅——第十一站 简单说说sqlserver的执行计划

原文:Sql Server之旅--第十一站 简单说说sqlserver的执行计划 我们知道sql在底层的执行给我们上层人员开了一个窗口,那就是执行计划,有了执行计划之后,我们就清楚了那些烂sql是怎么执行的,这样 就可以方便的找到sql的缺陷和优化点. 一:执行计划生成过程 说到执行计划,首先要知道的是执行计划大概生成的过程,这样就可以做到就心中有数了,下面我画下简图: 1. 分析过程 这三个比较容易理解,首先我们要保证sql的语法不能错误,select和join的表是必须存在的,以及你是有执行

Sql Server之旅——第四站 你必须知道的非聚集索引扫描

非聚集索引,这个是大家都非常熟悉的一个东西,有时候我们由于业务原因,sql写的非常复杂,需要join很多张表,然后就泪流满面了...这时候就 有DBA或者资深的开发给你看这个猥琐的sql,通过执行计划一分析...或许就看出了不该有的表扫描...万恶之源...然后给你在关键的字段加上非 聚集索引后...才发现提速比阿斯顿马丁还要快...那么一个问题来了,为什么非聚集索引能提速这么快...怎么做到的???是不是非常的好奇??? 这篇我们来解开神秘面纱. 一:现象 先让我们一睹非聚集索引的真容,看看到

Sql Server之旅——第七站 为什么都说状态少的字段不能建索引

我们在学sqlserver的时候,大多教科书和前辈们都说状态少的字段不要建索引,由此带来的开销还不如不建索引,但是这句话有多少人真的知道, 或者说有多少人真的对此有比较深刻的理解,而不是听别人道听途说...这样记得快,忘记的也不慢...这篇我来分析一下这句话到底有几个意思. 一:现象 首先我们还是用测试数据来发现问题,我先建立一个Person,有5个字段,建表sql如下: DROP TABLE dbo.Person CREATE TABLE Person(ID INT PRIMARY KEY I

Sql Server之旅——第六站 使用winHex利器加深理解数据页

这篇我来介绍一个winhex利器,这个工具网上有介绍,用途大着呢,可以用来玩数据修复,恢复删除文件等等....它能够将一个file解析成 hex形式,这样你就可以对hex进行修改,然后你就可以看到修复后的结果,为什么要在sqlserver系列中说这个呢???很简单呀,sqlserver的DB本 质上也是一个mdf文件,对吧,既然是文件,我就可以利用winhex对它进行随意的修改,然后你也知道sqlserver的数据都是以数据页的形式封装的, 那我就可以修改它的数据页,对不对,这样我就可以随便改变

Sql Server之旅——第十三站 对锁的初步认识

终于这个系列快结束了,马上又要过年了,没什么心情写博客...作为一个开发人员,锁机制也是我们程序员必须掌握的东西,很久之前 在学习锁的时候,都是教科书上怎么说,然后我怎么背,缺少一个工具让我们眼见为实...如果这样的话,学习一个东西就很容易忘记... 因为这些都是你背诵过来的...这篇的话我就来分享一个工具来帮助我们学习锁. 一:到底都有哪些锁 学习锁之前,必须要知道锁大概有几种???通常情况下作为码农我们只需知道如下几个锁即可... 1.S(Share)锁 为了方便理解,我们可以直接这么认为,

Sql Server之旅——第三站 解惑那些背了多年聚集索引的人

说到聚集索引,我想每个码农都明白,但是也有很多像我这样的猥程序员,只能用死记硬背来解决这个问题,什么表中只能建一个聚集索引, 然后又扯到了目录查找来帮助读者记忆....问题就在这里,我们不是学文科,,,不需要去死记硬背,,,我们需要的就是能看到在眼里面的 真实东西.....我们都喜欢聚集索引,因为它能够把无序的堆表记录变成有序,还玩起了B树...这样就把复杂度从N降低到了LogMN... 这样的话逻辑读,物理读就下来了. 一:现象 1:无索引的情况 还是老规矩,看个例子感受下,首先我有一个Pro

Sql Server之旅——第五站 确实不得不说的DBCC命令

今天研发中心办年会,晚上就是各自部门聚餐了,我个人喜欢喝干红,在干红中你可以体味到那种酸甜苦辣...人生何尝不是这样呢???正好 ceo从美国带了干红回来,然后我就顺道开心的过了把瘾....一个字...爽....喝着有点多...到现在头还疼....回来地铁上想这个 周末忙着找房子,书一点都没看,也没在博客上接着忽悠,想起了上篇博客有个哥们说普及普及DBCC,虽然有点迷迷糊糊的...看能不能写出点新 花样....不管学什么语言,还是数据库,你得看的比人家深一层...最可悲的就是停留的在表层,这样每

Sql Server之旅——第九站 看公司这些DBA们设计的这些复合索引

这一篇再说下索引的最后一个主题,索引覆盖,当然学习比较好的捷径是看看那些大师们设计的索引,看从中能提取些什么营养的东西,下面我们看 看数据库中一个核心的Orders表. 一:查看表的架构 <1> 先查看这个表的大概架构信息 1 --查看表的架构信息 2 SELECT c.column_id,c.name,t.name FROM sys.columns AS c 3 JOIN sys.types t 4 ON c.system_type_id=t.system_type_id 5 WHERE c