如果聚集索引是表数据,它怎么可能不唯一?

时间:2016-08-24 21:44:19

标签: sql-server sql-server-2008

我正在研究如何将table从一个filegroup移到另一个clustered indexes,我怀疑为什么我发现的大部分回复都涉及CREATE CLUSTERED INDEX,考虑到我的问题与表格有关。

然后我查看了How I can move table to another filegroup?,它说聚集索引是表数据,这解释了使用app.use(helmet.noCache());重新创建聚簇索引的原因。

但在同一个问题中,它说如果我的聚集索引是唯一的,那么就做其他事情。

我的问题:我假设当我在数据库上创建表时,会为该表创建聚簇索引。那么它怎么能不是唯一的呢?

感谢。

4 个答案:

答案 0 :(得分:3)

如果你有一个int数组并且在其中存储了两次1 - 该数组怎么不是唯一的?! (欺骗问题让你思考。它显然不是唯一的。)唯一的是数据上的约束。从根本上说,没有什么可以阻止您创建在所有列中具有相同值的多个行。

在堆中,这根本不是物理上的问题。内部行标识符是它在磁盘上的位置。

在基于b树的索引("聚簇索引")中,物理数据结构确实需要唯一性。注意,逻辑结构(表)没有。这是一个物理问题。这是一个实现细节。 SQL Server通过内部附加包含向上计数的序列号的键列来完成此操作。这消除了记录的歧义。您可以通过使用相同的非唯一键创建超过2 ^ 32行来观察此效果。您将收到错误。

因此,您无法访问表中的隐藏列。它正式被称为" uniqueifier"。在内部,它用于完成CI密钥以使其唯一。它通常在使用唯一CI密钥的任何地方存储和使用:在CI中,在非唯一NCI中,在锁定散列和查询计划中。

答案 1 :(得分:1)

如果群集索引不是唯一的,则SQL Server会在内部创建Uniquifier以使该记录具有唯一性。我将尝试用一个例子来解释:

CREATE TABLE Test2 (Col1 INT, Col2 INT)

CREATE CLUSTERED INDEX idxClustered ON Test2 (Col1) 
CREATE NONCLUSTERED INDEX idxNonClustered ON test2 (Col2) 

这里的cluserered索引不是唯一的

INSERT INTO Test2 VALUES (1,1), (2,2) 
INSERT INTO Test2 VALUES (3,3)
INSERT INTO Test2 VALUES (3,3)

--Get the Page Number of the Non Clustered Index
DBCC IND (Test, Test2, -1)

--Examine the Results of the Page
--Not to run in production
DBCC TRACEON (3604); 
DBCC PAGE(Test, 1, 3376, 3); 

您将看到具有相应唯一性值的Uniquifier键...如果您的聚簇索引是唯一聚簇索引,则它将不具有该Uniquifier属性。

答案 2 :(得分:1)

  

** usr *有一个值得阅读的好帖子。我将从Microsofts文档中添加。

首先,Clustered-Indexes并不孤单。老实说,名称本身有些令人困惑(结构化索引磁盘索引SQL中可能会更好)。

请参阅MSDN的官方文档。我的任何改动都在斜体

群集索引是表的磁盘上结构。这意味着值指向物理位置。这就是为什么当您移动表时,您需要重新创建索引,因为物理位置已被更改。

  

<强>群集

     
      
  • 聚簇索引在表或视图中对数据行进行排序和存储   基于他们的关键值。这些是索引中包含的列   定义。每个表可以有只有一个聚簇索引,因为   数据行本身可以按仅一个订单排序。

  •   
  • 表中数据行以排序顺序存储的唯一时间是   当表格包含clustered index时。当一张桌子有一个   在聚簇索引中,该表称为clustered table。如果一张桌子有   没有聚簇索引,其数据行存储在无序结构中   称为 heap

  •   
     

<强>非聚集

     
      
  • 非聚簇索引与数据行的结构分开类似于指针,这是消耗一小部分物理磁盘空间的数据的逻辑顺序)

  •   
  • 非聚集索引包含非聚簇索引键值和每个值   键值条目对包含键的数据行有 pointer   值。

  •   
  • 从非聚簇索引中的索引行到数据行的指针   被称为row locator。行定位器的结构取决于   数据页是存储在heap还是clustered table (按顺序排列)

  •   
  • 对于heap行定位器是指向该行的指针
  •   
  • 对于clustered table行定位器是聚集索引键
  •   

摘要视图

  1. 创建的表不一定是群集(有序)表。
  2. 索引不一定必须是唯一的。它是表格的抽象视图。
    • 唯一意味着一个值或一组值不会重复。如果您希望强制执行此操作,则可以通过索引(即UNIQUE CLUSTERED INDEX)或CONSTRAINT(例如PRIMARY KEY)添加约束(如果您希望在表结构本身中对其进行管理)。
  3. 您可能有多个唯一索引,因为只要值逻辑,它们就不会与另一个行指针共享相同的值。
  4. 考虑在给定的表中有A列,B列和C列。

    A列是使用UNIQUE CLUSTERED INDEX创建的。这意味着 A 已经具有可强制执行的UNIQUE约束(例如PKUNIQUE CONSTRAINT)或明确宣布。< / p>

    列组 {B,C} 可以是唯一索引,只要B和C不会一起重复。同样,理论上你可以使用 {A} {B,C} {A,C} 组的索引,他们每个人都是独一无二的。回想一下,索引是数据的逻辑顺序,因此它们可能不具有相同的逻辑值(因此是唯一的)。

    HOWEVER :除非数据类型,约束(包括INDEX约束)或表结构对COLUMN强制执行唯一约束,否则您不应假设索引是唯一的。此外,如果有多个行包含UNIQUE值的相同组合,则无法创建NULL索引,因为SQL Server会将它们视为相同的值(NULL未知)。 / p>

    SQL Server会使用您的索引,是否唯一?那是另一个故事,取决于许多事情。但希望你发现这篇文章很有帮助。

    <强>来源: MSDN - Clustered and Nonclustered Indexes Described

答案 3 :(得分:0)

聚集索引不必是唯一的。但是,表上只能有一个聚簇索引,因为聚簇索引实际上确定了磁盘上表行的物理顺序(但我发现表示聚簇索引 表时很困惑数据本身,即使它们彼此紧密相关)。

HERE是关于非唯一聚簇索引的好帖子。即使索引是整行数据,您当然也可以有重复的行(没有PK),这相当于重复的聚簇索引节点。