INDEX--从数据存放的角度看索引2

在上次<INDEX--从数据存放的角度看索引>中,我们说到"唯一非聚集索引"和“非唯一非聚集索引”在存储上有一个明显的差别:唯一非聚集索引的非叶子节点上不会包含RID的数据,让我们继续来深挖一下。

准备测试数据:

CREATE TABLE TB1
(
    C1 INT,
    C2 INT,
    C3 INT
)
GO
CREATE UNIQUE CLUSTERED INDEX IDX_C1 ON TB1(C1)
GO
CREATE UNIQUE INDEX IDX_C2 ON TB1(C2)
GO
CREATE INDEX IDX_C3 ON TB1(C3)
GO
INSERT INTO TB1(C1,C2,C3)VALUES(1,1,1)
GO
INSERT INTO TB1(C1,C2,C3)VALUES(2,2,2)
GO
INSERT INTO TB1(C1,C2,C3)VALUES(3,3,3)

索引编号如下:

再通过DBCC IND和DBCC PAGE来查看页情况

唯一非聚集索引IDX_C2的数据页:

非唯一非聚集索引IDX_C3的数据页:

以上两张图有个明显的区别是C1和C1(key),难道在“非唯一非聚集索引”中,“聚集索引键”也被放到“非聚集索引键”中并且参与排序啦?

相信很多DBA的朋友都遇到这样的问题,要按照某些状态值来查找数据,而这些状态值是一个很小的集合(数量很小),如查找状态值为1的最大订单号

SELECT TOP(1)*
FROM dbo.Orders
WHERE OrderState=1
ORDER BY OrderID DESC 

虽然OrderID为主键和唯一聚集索引,但按照OrderID来查找,可能需要进行大范围CLUSTERED INDEX SEEK才能找到满足条件OrderState=1的数据,因此尽管OrderState的可选择性较低,我们还是会对其建立索引,那么问题来了?我们索引该建成什么样呢?
是建成:

CREATE INDEX IDX_OrderState
ON dbo.Orders
(
    OrderState
)

还是建成:

CREATE INDEX IDX_OrderState
ON dbo.Orders
(
    OrderState,
    OrderID
)

曾经我想当然地认为必须建成第二种方式,因为还需要对OrderID进行排序取TOP(1),但经过测试,神奇地发现两种方式的效率一样,无论“非唯一非聚集索引键”里有没有包含“聚集索引键”,都会对“非唯一非聚集索引键”+“聚集索引键”进行排序。

思考这样一个问题,假设对“非唯一非聚集索引键”,仅仅对其定义的键进行排序,如OrderState,而满足OrderState=0的可能有1亿数据,在进行数据更新的时候,首先更新聚集索引,并依次更新非聚集索引,更新索引数据首先要定位数据行才能更新,因此需要扫描这1亿数据才能找到目标行,显然这是不可接受的设计。

对于"唯一非聚集索引"来说,因为可以通过索引键便可以快速定位到索引数据行,且每个键值只会存在一行,因此失去了对“聚集索引键”进行排序的意义。

BTW, 也可以通过观察相同键值下行位置(slotid)和插入顺序来发现数据按照聚集索引键排序。

--===========================================================================

总结:

1. 对于“非唯一非聚集索引”,索引数据实际上是按照“非唯一非聚集索引键”+“聚集索引键”进行排序后存放的;

2.  对于“唯一非聚集索引”,索引数据实际上是按照“唯一非聚集索引键”进行排序后存放的;

3. 所有非聚集索引的叶子节点上都会存放RID的数据,但唯一非聚集索引的非叶子节点上不会包含RID的数据;

--===========================================================================

好好读书。。。

时间: 2024-12-22 07:36:24

INDEX--从数据存放的角度看索引2的相关文章

INDEX--从数据存放的角度看索引

测试表结构: CREATE TABLE TB1 ( ID INT IDENTITY(1,1), C1 INT, C2 INT ) 1. 聚集索引(Clustered index) 聚集索引可以理解为一个包含表中除索引键外多有剩余列的包含索引,为保证在DELETE/UPDATE操作的正确性,如果聚集索引未声明为唯一(UNIQUE),则系统会聚集索引键增加一个NULLABLE的INT类型标识列(UNIQUIFIER)以保证记录唯一性. 唯一聚集索引: CREATE UNIQUE CLUSTERED

从节能角度看数据中心软硬件设计(一)

从节能角度看数据中心软硬件设计(一) -PMC公司资深顾问.前Facebook存储架构设计师. OCP创始人之一Per Brasher于CCCC演讲实录- 此次演讲流程如下.首先讨论关注数据中心效率的原因及其提升效率的原始动力所在.第二步讨论影响效率的主要构成部件,这些部件对效率的贡献大概有多少,以及怎样对每个部件的效率进行优化和提高.第三个方面是展望如何进一步降低TCO成本,其中将涉及更先进的数据保护机制.接着会对存储的各种新模式进行一定展望,最后做一个总结. 下表总结了OCP的设计理念,其中

MySQL在创建数据表的时候创建索引

转载:http://www.baike369.com/content/?id=5478 MySQL在创建数据表的时候创建索引 在MySQL中创建表的时候,可以直接创建索引.基本的语法格式如下: CREATE TABLE 表名(字段名 数据类型 [完整性约束条件], [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY [索引名](字段名1 [(长度)] [ASC | DESC]) ); UNIQUE:可选.表示索引为唯一性索引. FULLTEXT:可选.表示索引为全

终端角度看RSA

首先关于RSA: RSA的算法涉及三个参数,n.e1.e2. 其中,n是两个大质数p.q的积,n的二进制表示时所占用的位数,就是所谓的密钥长度. e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质:再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1. (n,e1),(n,e2)就是密钥对.其中(n,e1)为公钥,(n,e2)为私钥. A=B^e2 mod n:B=A^e1 mod n(e1和e2可以互换使用,即:A=B^e1mod n:B=A^e2

内存角度看c#中值类型和引用类型的区别(转)

1.    值类型的数据存储在内存的栈中:引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址. 2.     值类型存取速度快,引用类型存取速度慢. 3.     值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用 4.     值类型继承自System.ValueType,引用类型继承自System.Object 5.     栈的内存分配是自动释放:而堆在.NET中会有GC来释放 6.      值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的

另一种角度看《RFID Advanced Security》首部曲

机缘巧合,有幸看到了不少关于RFID的资料,并且有幸看到了<RFID Advanced Security>这份PDF,听说这是国内安全大会上比较早出现关于RFID的议题.又听说这份是乌云内部的高级教程,文章内容单薄是无可厚非,毕竟是演讲,单单时间上来说不可能什么都讲.看完了以后实在有点不(fei)知(yi)所措(si),因为槽点实在是太多了. 文章分成4大块,分别为"RFID Basic Knowledge.RFID Basic System Security.RFID Multip

CREATE INDEX 语句用于在表中创建索引

CREATE INDEX 语句用于在表中创建索引. 在不读取整个表的情况下,索引使数据库应用程序可以更快地查找数据. 索引 您可以在表中创建索引,以便更加快速高效地查询数据. 用户无法看到索引,它们只能被用来加速搜索/查询. 注释:更新一个包含索引的表需要比更新一个没有索引的表更多的时间,这是由于索引本身也需要更新.因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引. SQL CREATE INDEX 语法 在表上创建一个简单的索引.允许使用重复的值: CREATE INDEX ind

一起talk C栗子吧(第一百三十二回:C语言实例--从内存的角度看进程和线程)

各位看官们,大家好,上一回中咱们说的C程序内存布局的例子,这一回咱们说的例子是:从内存的角度看进程和线程.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们刚刚介绍完C程序的内存布局,我们趁热打铁,从内存的角度来分析一下进程和线程. 不管是进程还是线程,他们都会加载到内存中才能运行,因此他们在内存中的布局和其它C程序的内存布局完全相同.进程和线程的内存布局也分为代码区,数据区,堆区和栈区. 对进程来说,父子进程只共享代码区中的内容,父子进程拥有各自的数据区,堆区和栈区.而且它们只能

数据定义语言DDL - 视图索引

视图是虚拟表,主要用于方便使用和安全性,如: 按照条件筛选和过滤行 保护敏感数据 降低复杂程度 抽象逻辑数据库 在使用视图时需要注意: 视图中可以包含多张表 视图可以基于视图再次创建 视图也允许增删改 如果排序ORDER BY,则必须使用TOP关键字 不能出现INTO关键字 不能出现变量 创建视图的语法 create view view_detail as select g.id as gid, g.name as gname, c.id as cid, c.name as cname from