计算列、索引、聚集索引和覆盖索引?

Raz*_*t4x 7 index sql-server-2008

我们都知道每个表只能有一个集群视图,很酷。但显然,即使使用聚集索引,叶上也没有计算列的值,并且每次都会计算它们。
所以,我的第一个问题是,我刚才所说的是否正确?

另外,如果你创建一个聚集索引,好吧,让我引用......
“如果你在一个计算列上创建一个聚集索引,列的值将物理存在于相应的表行中,因为聚集索引的叶页包含数据行。”
是的,好的,但为什么只在计算列上创建聚集索引?我想如果你在任何列上创建一个聚集索引,那么叶上存在数据吗?
那么,我的问题 2 是如果我们仅在该特定列上创建聚集索引,计算列的值是否会存在(持久)在表中?(问题 2 继续)如果确实如此,如果我们有多个计算列怎么办?当然,我们不能创建多个聚集索引,那么我们如何使它们的值持久化?

现在继续,覆盖指数怎么样?首先,我们在创建聚集索引时并不真的需要覆盖(或者我们不能真正创建)覆盖索引,因为所有数据都已经在叶子上,对吗?那么,包括任何其他列没有意义吗?
那么,第三,我想问一下,我刚才在之前的发言中所说的是否正确?

现在,如果我们正在创建一个覆盖索引(非聚集,对吗?)并且我们包含计算列,那么我们会保留它们吗?它们会被“物理存储”还是再次计算?(顺便说一下,这是我的第四个问题。)

最后,(第 5 个问题)如果我们可以通过所有这些方式(或其中一些方式,我真的不知道是哪一种,这就是我首先提出这个问题的原因!)那么,最好的方法是什么,为什么?

ps:如果我只问了一次 5 个问题,我很抱歉,但它们都非常相关,我不想在 5 个不同的问题中一遍又一遍地问同样的问题。我希望你明白!:)

编辑:很好地回应评论,现在我正在使用 SQL Server 2008,但是如果您能提供如果使用其他任何东西(我的 sql 或其他任何东西),情况会如何不同,这不仅对我而且对社区都有好处. :)

Mar*_*ith 4

计算列可以通过两种方式之一存储在数据页中。通过将它们创建为PERSISTED聚集索引定义或将它们包含在聚集索引定义中。

如果它们包含在聚集索引定义中,那么即使列没有标记为,PERSISTED值仍将存储在每行中。这些索引键值将另外存储在上层页面中。

如果计算列不精确(例如float)或不可验证为确定性(例如 CLR 函数),则需要将该列标记为PERSISTED以便成为索引键的一部分。

举个例子

CREATE TABLE T
(
A INT,
C1 AS REPLICATE(CHAR(A),100) PERSISTED,
C2 AS REPLICATE(CHAR(A),200),
C3 AS CAST(A AS FLOAT) PERSISTED,
C4 AS CAST(A + 1 AS FLOAT)
)

CREATE UNIQUE CLUSTERED INDEX IX ON T(C2,C3)
Run Code Online (Sandbox Code Playgroud)
  • C1将仅存储在数据页行中,因为它被标记为 PERSISTED但未索引。
  • C2由于它是索引键列,因此将存储在数据页上的行和索引更高级别中。
  • C3将被存储为C2. 事实上,imprecise需要将其标记为PERSISTED然而。
  • C4不会存储在任何地方,因为它既没有标记为PERSISTED也没有索引。

同样,在非聚集索引定义中引用为键列的所有计算列都需要存储在索引的所有级别,因为它们是索引键的一部分。对于精确/确定性结果也有相同的要求。

失败

CREATE NONCLUSTERED INDEX IX2 ON T(A,C4)
Run Code Online (Sandbox Code Playgroud)

随着错误。

无法在表“T”上创建索引或统计信息“IX2”,因为计算列“C4”不精确并且未持久化。考虑从索引或统计键中删除列或将计算列标记为持久。

要将其作为非聚集索引键的一部分,它还必须存储在聚集索引数据页中。然而

成功了。

CREATE NONCLUSTERED INDEX IX2 ON T(A) INCLUDE (C4)
Run Code Online (Sandbox Code Playgroud)

仅是 d 列的计算列INCLUDE会持久保存到 NCI 叶页,并且不要求它们也持久保存在数据页中。