zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

server索引SQL 区别 之旅 到底 include 复合
2023-09-14 08:57:28 时间

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

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

索引和锁,这两个主题对我们开发工程师来说,非常的重要。。。只有理解了这两个主题,我们才能写出高质量的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表中各个槽位的信息

1 DBCC TRACEON(2588,3604)

2 DBCC IND(Ctrip,test1,-1)

3 DBCC PAGE(Ctrip,1,194,1) 


Slot 0, Offset 0x60, Length 27, DumpStyle BYTE

Record Type = INDEX_RECORD Record Attributes = NULL_BITMAP Record Size = 27

Memory Dump @0x000000000FB0A060

0000000000000000: 16616161 61613131 31407171 2e636f6d †.aaaaa111@qq.com 

0000000000000010: c0000000 01000000 030000†††††††††††††........... 

Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE

Record Type = INDEX_RECORD Record Attributes = NULL_BITMAP Record Size = 27

Memory Dump @0x000000000FB0A07B

0000000000000000: 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表中各个槽位信息

1 DBCC TRACEON(2588,3604)

2 DBCC IND(Ctrip,test2,-1)

3 DBCC PAGE(Ctrip,1,207,1)


Slot 0, Offset 0x60, Length 27, DumpStyle BYTE

Record Type = INDEX_RECORD Record Attributes = NULL_BITMAP Record Size = 27

Memory Dump @0x000000000DFCA060

0000000000000000: 16616161 6161c400 00000100 00003131 †.aaaaa........11 

0000000000000010: 31407171 2e636f6d 030000†††††††††††††1@qq.com... 

Slot 1, Offset 0x7b, Length 27, DumpStyle BYTE

Record Type = INDEX_RECORD Record Attributes = NULL_BITMAP Record Size = 27

Memory Dump @0x000000000DFCA07B

0000000000000000: 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

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:  这个我想你也懂,也就是111@qq.com。

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

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

 



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

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

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

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


没有索引也能用SQL ?深度解析 SLS Schema-on-Read 分析原理与应用 为了能够更灵活的挖掘日志数据背后的价值,SLS提出了一种不需要事先建立索引就能对数据进行分析的模式。本文对SLS Schema-on-Read分析的提出背景、设计思路、实现过程、使用方式、适用场景进行了全面的介绍。
SQL语句命中索引,但还是执行很慢 MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值(默认值10s)的SQL,则会被记录到慢查询日志中。
SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估) 原文:SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估) 本文出处:http://www.cnblogs.com/wy123/p/6008477.html  关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里。
数据库查询索引(sql单个索引和复合索引) 数据库查询索引(sql单个索引和复合索引)http://www.bieryun.com/3380.html 当一条sql语句的查询涉及到多个字段,这个时候给每个字段加索引,数据库也只能够使用其中的一个索引,这个时候使用复合索引就比较好了。
数据库查询索引(sql单个索引和复合索引) 数据库查询索引(sql单个索引和复合索引) 当一条sql语句的查询涉及到多个字段,这个时候给每个字段加索引,数据库也只能够使用其中的一个索引,这个时候使用复合索引就比较好了。这是为什么呢? 这是因为:全表扫描/只使用一个索引的速度比起来,去分析两个索引二叉树更加耗费时间,所以绝大多数情况下数据库都是是用一个索引。
第十二届 BigData NoSQL Meetup — 基于hbase的New sql落地实践 立即下载