【问题标题】:Are indexes basically a copy of the tables?索引基本上是表的副本吗?
【发布时间】:2018-12-17 00:13:05
【问题描述】:

今天我参加了一次工作面试,在那里我听说“索引基本上是表格的克隆,它们是在上面制作的”。

有人能理解这个说法吗?老实说,我从来没有听说过这种索引定义

【问题讨论】:

  • 已经有很多讨论和分享了,stackoverflow.com/questions/1108/…
  • 这在很大程度上是错误的,即使我们谈论的是聚集索引——更准确的说法是聚集索引表,而不是表的克隆。虽然非聚集索引确实包含表中的数据副本(这就是覆盖索引的原因),但它们的结构与基表不同。 “克隆”是一个误导性术语,但值得牢记的是索引会冗余复制数据(无论好坏)。
  • SQL Server docs.microsoft.com/en-us/sql/relational-databases/indexes/… 中有大约 12 种不同类型的索引。如果他们的采访者指的是特定类型的索引 - 他们应该指定。即便如此,这里也有很多人不同意这种说法。

标签: sql sql-server indexing database-indexes


【解决方案1】:

不是真的,虽然他们可能是。

每个索引(包括聚集索引)都将在其所有内部节点中使用索引keys。不同的是当我们到达索引的叶子时会发生什么。

在 SQL Server 中一个普通的老式非聚集索引中,您会在叶子中找到聚集索引的键值(或堆表的某种形式的行 ID)。而在聚集索引中,您会找到所有列的值,而不仅仅是聚集键和(对于该索引)特定键的值。

索引中的INCLUDE 在非聚集索引中包含叶级别的额外列,从而使水有些混乱。

如果非聚集索引(索引键、聚集索引键、包含列)中的总列集与表中所有列的集相同,则在一定程度上非聚集索引似乎确实是表的副本 - 至少在使用此索引的任何查询都不必执行任何表查找来检索所有数据的范围内。

如果上面的列集与表中所有列的集不同,则它不是表的副本。它是表列子集的副本。当然,如果这个列子集是特定查询所需的所有列,那么仍然可以避免查表。

【讨论】:

  • 我提出了另一个问题:非聚集索引是否包含叶子中的任何数据或仅包含堆的聚集索引键值/RID - 到数据?
  • @Rocket128 - 它将包括非聚集索引键、查找值(聚集键/RID)和任何INCLUDE 列。
  • 因此,没有包含列的基本非聚集索引将不包含任何数据。基表中的实际数据只有集群键/RID。我说的对吗?
  • @Rocket128 - 请记住,叶子仍然(可能)覆盖多个不同的值。这就是为什么我说非聚集索引键也在其中。
  • @Rocket128 - 此索引的实际键。如果此索引在 a,b 上,并且聚集索引在 c,d 上,那么在叶子上,我们将有一个或多个条目显示“对于 这些 a,b 值,查找这些行" 后跟一组 c,d 对。
【解决方案2】:

如果您谈到聚集索引,那是真的。只需检查文档:

聚集索引对表或视图中的数据行进行排序和存储 基于它们的关键值。这些是索引中包含的列 定义。每个表只能有一个聚集索引,因为 数据行本身只能以一种顺序存储。

表中的数据行按排序顺序存储的唯一时间是 当表包含聚集索引时。当一个表有一个 聚集索引,该表称为聚集表。如果一个表有 没有聚集索引,它的数据行存储在一个无序的结构中 称为堆。

但是,如果您谈到非聚集索引,那么它是错误的,因为表存储是一个与表分离的堆和索引。在这种情况下,索引是另一个看起来像数据结构的对象。

非聚集索引具有独立于数据行的结构。一种 非聚集索引包含非聚集索引键值和每个 键值条目有一个指向包含该键的数据行的指针 价值。

从非聚集索引中的索引行到数据行的指针是 称为行定位器。行定位器的结构取决于 数据页是存储在堆还是聚簇表中。为了 一个堆,一个行定位器是一个指向行的指针。对于聚簇表, 行定位器是聚集索引键。

您可以将非键列添加到非聚集索引的叶级 绕过现有的索引键限制,并完全覆盖执行, 索引,查询。有关详细信息,请参阅创建索引 包含的列。有关索引键限制的详细信息,请参阅最大值 SQL Server 的容量规格。

【讨论】:

    猜你喜欢
    • 2014-12-05
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 2018-09-20
    相关资源
    最近更新 更多