1

我有一个关于聚集索引的问题。

在聚集索引中,叶级节点本身按排序顺序保存数据,对吗?

也就是说,每次插入/更新/删除时,节点都会重新洗牌以保持排序顺序。

那么如何按照插入的顺序从中检索数据呢?

想象一下按照给定的顺序插入以下数据:1,7,4,5,2并在该字段上创建聚集索引。

那么数据将按顺序存储在内部1,2,4,5,7吗?

所以这可能有助于更快地查找特定值,但是如果用户想要按照他插入的顺序排列前 3 个值怎么办?

它们是否可以以某种方式检索,或者我是否必须为插入的每一行分配一个增量 id,在其上声明一个非聚集索引,并根据对该 id 字段上的记录进行排序来提供前 3 条记录的数据?

4

3 回答 3

2

(基于 SQL Server 的答案 - 问题没有 100% 指定)

在聚集索引中,叶级节点本身按排序顺序保存数据,对吗?

这不太正确,数据可以以任何顺序存储在叶子上,但页面上的插槽数组实际上是从页面读取数据的顺序 - 而不是数据的物理顺序。

也就是说,每次插入/更新/删除时,节点都会重新洗牌以保持排序顺序。

节点(例如页面被拆分并且双链表上的前向/后向指针改变),但在页面内,槽数组仍然是保留顺序的实体,行本身不会被打乱以匹配槽数组顺序。

那么如何按照插入的顺序从中检索数据呢?

通常不保证它会按照确切的顺序 - 这往往发生在堆页面上,其中插槽数组更能代表顺序,但同样不能保证。

想象一下,按照给定的顺序插入以下数据:1、7、4、5、2,并在该字段上创建聚集索引。所以数据将按 1、2、4、5、7 的顺序在内部存储,对吗?

不,它将在页面上存储 1,7,4,5,2,但插槽数组会将页面上的地址读取为 7,5,4,2,1(它从页面末尾向后构造,所以你倒着读。)

所以这可能有助于更快地查找特定值,但是如果用户想要按照他插入的顺序排列前 3 个值怎么办?

在这种情况下有点无关紧要——除了没有关于排序的保证之外,SQL 会将整个页面读入内存。如果你想了解更多关于这种级别的 SQL 内部知识,我仍然会推荐 Kalen Delaneys SQL Internals 这本书作为最好的来源之一。

如果您想了解有关插入顺序的任何信息,我建议您使用某种 insert_timestamp

于 2012-07-01T19:26:43.043 回答
1

表数据按照聚集索引的顺序进行排序。每个表只能有一个聚集索引,如果你想按照他插入的顺序检查前 3 个值,

使用 AdventureWorks

CREATE TABLE myTable99(
Col1 int IDENTITY(1,1) PRIMARY KEY , Col2 Char(1) , Col3 datetime DEFAULT getdate()

) 去

INSERT INTO myTable99(Col2) SELECT 'A' UNION ALL SELECT 'B' UNION ALL SELECT 'C' 去

SELECT * FROM myTable99 ORDER BY 3 GO

删除表 myTable99 去

其他方法可能是:

CREATE TABLE CounterData]( [CounterDataID] [bigint] IDENTITY(1,1) NOT NULL, [DateTimeID] [bigint] NOT NULL, [Value] [float] NULL ) ON [PRIMARY]

在 [PK].[CounterData] 上创建唯一的聚集索引 [IX_DateTime_CounterDataID]

(

[DateTimeID] ASC,
[CounterDataID] ASC

)

(PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,SORT_IN_TEMPDB = OFF,IGNORE_DUP_KEY = OFF,DROP_EXISTING = OFF,ONLINE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 开始

于 2012-07-01T19:47:49.320 回答
1

听起来你想在你的行上给我一个时间戳。我通常会在我创建的所有表上放置以下列(用于审计):

timecreated
timemodified
createdby
modifiedby
deleted

这些列让您知道谁创建了该行以及何时、何时最后修改以及由谁以及可选地“软删除”该行,方法是将已删除设置为 true。当然,系统中的所有其他查询都必须检查已删除的布尔值才能使软删除起作用。

于 2012-07-01T19:25:40.600 回答