我对聚集索引有疑问。
在聚簇索引中,叶级节点本身按排序顺序保存数据,对吧?
也就是说,对于每次插入/更新/删除,对节点进行重新洗牌以维持排序顺序。
那么如何以插入的顺序从中检索数据呢?
想象一下,按照给定的顺序插入以下数据:1,7,4,5,2
并在此字段上创建聚簇索引。
那么数据将按照1,2,4,5,7
的顺序在内部存储吗?
因此,这可能有助于更快地查找特定值,但如果用户想要按照插入的顺序获得前3个值,该怎么办?
它们是否以某种方式可检索,或者我是否必须为插入的每一行分配增量ID,在其上声明非聚集索引,并根据对该id字段的记录进行排序来提供前3条记录的数据?
答案 0 :(得分: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 Internals,我仍然会推荐Kalen Delaneys SQL Internals书作为最好的资源之一。
如果您需要有关插入顺序的任何信息,我建议使用某种inserted_timestamp
答案 1 :(得分:1)
听起来你想在我的行上添加时间戳。我通常在我创建的所有表(用于审计)上放置以下列:
timecreated
timemodified
createdby
modifiedby
deleted
通过这些列,您可以通过将删除设置为true来告知您是谁创建了行以及何时,何时进行上次修改以及由谁以及可选地“软删除”该行。当然,系统中的所有其他查询都必须检查已删除的布尔值,以便软删除工作。
答案 2 :(得分:1)
表数据根据聚簇索引的顺序排序。 如果您想按照插入的顺序检查前3个值,则每个表上只能有一个聚簇索引,
USE AdventureWorks
去
创建表myTable99(
Col1 int IDENTITY(1,1)PRIMARY KEY,Col2 Char(1),Col3 datetime DEFAULT getdate())GO
INSERT INTO myTable99(Col2)SELECT'A'UNION ALL SELECT'B'UNION ALL 选择'C'GO
SELECT * FROM myTable99 订购3 GO
DROP TABLE myTable99 GO
其他方法可能是:
CREATE TABLE CounterData]([CounterDataID] [bigint] IDENTITY(1,1)NOT NULL,[DateTimeID] [bigint] NOT NULL,[Value] [float] NULL)ON [PRIMARY]
创建独特的聚类索引[IX_DateTime_CounterDataID] ON [PK]。[CounterData]
(
[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] GO