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

简介: 原文:Sql Server之旅——第八站 复合索引和include索引到底有多大区别?  周末终于搬进出租房了,装了宽带。。。。才发现没网的日子。。。那是一个怎样的与世隔绝呀。。。再也受不了那样的日子了。
原文: 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','111@qq.com')
 4 INSERT INTO test1 VALUES(2,'bbbbb','222@qq.com')
 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','111@qq.com')
10 INSERT INTO test2 VALUES(2,'bbbbb','222@qq.com')
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:  这个我想你也懂,也就是111@qq.com。

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

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

 

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

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

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

 

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

 

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

 

目录
相关文章
|
8月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
11月前
|
SQL 存储 关系型数据库
SQL优化策略与实践:组合索引与最左前缀原则详解
本文介绍了SQL优化的多种方式,包括优化查询语句(避免使用SELECT *、减少数据处理量)、使用索引(创建合适索引类型)、查询缓存、优化表结构、使用存储过程和触发器、批量处理以及分析和监控数据库性能。同时,文章详细讲解了组合索引的概念及其最左前缀原则,即MySQL从索引的最左列开始匹配条件,若跳过最左列,则索引失效。通过示例代码,展示了如何在实际场景中应用这些优化策略,以提高数据库查询效率和系统响应速度。
497 10
|
SQL 索引
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
|
SQL 关系型数据库 OLAP
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
495 2
|
SQL Oracle 关系型数据库
SQL优化-使用联合索引和函数索引
在一次例行巡检中,发现一条使用 `to_char` 函数将日期转换为字符串的 SQL 语句 CPU 利用率很高。为了优化该语句,首先分析了 where 条件中各列的选择性,并创建了不同类型的索引,包括普通索引、函数索引和虚拟列索引。通过对比不同索引的执行计划,最终确定了使用复合索引(包含函数表达式)能够显著降低查询成本,提高执行效率。
304 3
|
SQL 关系型数据库 MySQL
如何确认SQL用了索引:详细技巧与方法
在数据库管理中,索引是提高SQL查询性能的重要手段
2647 5
|
SQL 存储 关系型数据库
SQL默认索引是什么:深入解析与技巧
在SQL数据库中,索引是一种用于提高查询性能的重要数据结构
|
6月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1127 152
|
6月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
861 156
|
6月前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
595 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库