考虑聚集表,
Quassnoi写道(答案中的最后一句话):
这听起来像群集密钥被添加到非唯一非聚集索引的(所有)中间节点中。并且通过相同的逻辑,在非聚集表的情况下将RID添加到中间节点(?)
它的目的是什么?
更新
目前这个问题有9票:-5,+ 4,仅从匿名开始-3),
正确答案与大多数msdn文档相矛盾
它的价值实际上并不是本身,而是如何解决与SQL Server内部相关的这类问题,无论是在文档中是矛盾的还是错误的或不充分的描述。
更新2: @Quassnoi,
感谢您的回答,丰富了我调查自己的能力,而没有提出愚蠢的问题。
DBCC IND()不输出PageID。我不知道它的PagePID(来自DBCC IND的输出)对应于DBCC DBCC Page()输出中的PageID。
我对他们的使用(以及内部研究/调查)或其他替代方案有更多疑问。我不确定为什么这类问题在这里被认为是垃圾邮件
你可以告诉我这类问题的适当论坛/董事会(在SQL Server内部)吗?
答案 0 :(得分:4)
这听起来像群集密钥被添加到非唯一非聚集索引的(所有)中间节点中。并且通过相同的逻辑,在非聚集表的情况下将RID添加到中间节点(?)
是的,这是真的。
这样做是为了提高索引的可维护性。
假设您在column
,1,000,000
记录中有column = 1
的辅助(非群集)索引,并希望删除其中一条记录。
记录也需要从索引中删除。
要找到要删除的记录,应对索引执行B-Tree
搜索。但是,如果分支节点没有存储行指针的值(无论是聚簇键还是RID
),引擎必须扫描所有1M
条记录以确定要删除的记录。 / p>
如果辅助密钥是UNIQUE
,则column
的值足以唯一地定位索引中的节点,因此不需要将行指针存储在分支节点中(并且为什么他们没有存储。)
您可能也对此讨论感兴趣:
http://www.sqlservercentral.com/Forums/Topic714684-1545-6.aspx
<强>更新强>
要检查分支节点的内容,可以使用DBCC IND
:
CREATE TABLE t_clustered (id INT NOT NULL PRIMARY KEY, nval INT, uval INT)
CREATE TABLE t_nonclustered (id INT NOT NULL PRIMARY KEY NONCLUSTERED, nval INT, uval INT)
CREATE INDEX ix_clustered_nval ON t_clustered (nval)
CREATE UNIQUE INDEX ux_clustered_uval ON t_clustered (uval)
CREATE INDEX ix_nonclustered_nval ON t_nonclustered (nval)
CREATE UNIQUE INDEX ux_nonclustered_nval ON t_nonclustered (uval)
;
WITH q(id) AS
(
SELECT 1
UNION ALL
SELECT id + 1
FROM q
WHERE id < 10000
)
INSERT
INTO t_clustered
SELECT id, (id - 1) / 10 + 1, id
FROM q
OPTION (MAXRECURSION 0)
;
WITH q(id) AS
(
SELECT 1
UNION ALL
SELECT id + 1
FROM q
WHERE id < 10000
)
INSERT
INTO t_nonclustered
SELECT id, (id - 1) / 10 + 1, id
FROM q
OPTION (MAXRECURSION 0)
-- Replace mydb with your database name
DBCC IND (mydb, t_clustered, -1)
DBCC IND (mydb, t_nonclustered, -1)
在这些命令的输出中,您应该搜索PageType = 2
(索引页)和IndexLevel > 0
(非叶节点)的记录,并找到他们的PageID
。
在我的情况下,我得到以下PageID
:21074,21076,21105,21107。注意它们是特定于站点的:您将拥有其他值。
然后你应该使用DBCC PAGE
来检查这些页面的内容:
DBCC PAGE (mydb, 1, 21074, 3)
DBCC PAGE (mydb, 1, 21076, 3)
DBCC PAGE (mydb, 1, 21105, 3)
DBCC PAGE (mydb, 1, 21107, 3)
FileId PageId Row Level ChildFileId ChildPageId nval (key) id (key) KeyHashValue
FileId PageId Row Level ChildFileId ChildPageId uval (key) KeyHashValue
FileId PageId Row Level ChildFileId ChildPageId nval (key) HEAP RID (key) KeyHashValue
FileId PageId Row Level ChildFileId ChildPageId uval (key) KeyHashValue
我们看到nval
上的非唯一二级索引的非叶节点包含记录指针(id (PRIMARY KEY CLUSTERED)
和RID
,适当地),而那些唯一索引上的uval
不包含记录指针,只包含索引列本身的值。
这又是因为使用唯一索引,索引列的值足以在索引中定位其节点,而使用非唯一索引则不是。
答案 1 :(得分:1)
你正在问其他人所说的问题而不了解主题(IT; B-Trees;索引结构),他们所说的,做出了陈述。这是一个答案服务,而不是辅导服务。
“这听起来像群集密钥被添加到非唯一非聚集索引的(所有)中间节点”
没有。 Quassnoi没有说那种。您不能接受陈述(在上下文中的答案;问题)并单独评估它们。 CI键仅 适用于叶级别,而不适用于“中间节点”。
“并且在非集群表(?)的情况下,通过相同的逻辑将RID添加到中间节点”
逻辑?再也没有。确定大象尾巴是由厚而长的毛发制成的,并不意味着躯干也是由头发制成的。
向另一个问题提出非唯一的非聚集索引的非叶节点。关于非问题,我有点不加分。
答案。对于您现在始终如一的理解水平,非聚集索引具有完整的聚簇键值作为叶级别的条目。期。故事结局。这没什么大不了的,因为(a)步骤的数量是相同的(b)CI索引(不是叶子)无论如何都将在缓存中,因此非常快,不需要磁盘访问直到最后(叶级别)。 / p>
NCI密钥查找,无CI: 索引查找 - &gt; RID - &gt;数据行查找 - &gt;数据行
NCI密钥查找,CI: 索引查找 - &gt; CI键 - &gt;聚集索引查找 - &gt;数据行
它的目的是什么?
性能。所有供应商都知道,查询激活的函数链中最慢的组件是磁盘,它是唯一具有移动部件的组件。他们都尽力避免磁盘访问,并提高性能。自1960年代以来,索引本身就是避免磁盘访问的最基本结构。从那以后,基本的B-Tree没有改变,它只有一百万个小小的进步。
现在的问题是,虽然这是真的,但每个供应商都有(a)有自己的一些特殊技术,可以增强(添加,不改变我发布给你的基本操作)操作和(b)在MicroShifty世界中,它一直在变化,因为增强功能并非真正的增强功能。重点是,极低的水平与理解指数如何运作无关;或CI或NCI是否适合您的特定用途;或者各自的优点/缺点。
我已经确定,为了帮助你,不要介入较低级别,直到你了解基础知识,更高级别...如果你这样做,你会迷路,这将是一个障碍你表达的学习意图。正如这里所证明的那样试。