4

我在 Stackoverflow 看到了这篇文章。第一个答案提到诸如聚集索引具有表的所有数据,而非聚集索引仅具有列+聚集索引的位置或行(如果它在堆上)(没有聚集索引的表)。非聚集索引如何获得聚集索引的位置?它只包含在 B 树中排序为节点的列值,每个节点都固定到该列具有该节点值的行,对吗?

4

2 回答 2

4

假设您正在谈论SQL Server,并且还假设您的表上一个聚集索引(您应该这样做)。

然后,非聚集索引具有您在CREATE INDEX语句中定义的列,以及构成聚集索引(如果存在)的列。

该聚类键值是指向实际数据所在位置的“指针”。

如果查询执行器在您的非聚集索引中寻找一个值并找到匹配项,那么

  • 要么该值就是您所关心的-然后您就可以取回该值

  • 或者非聚集索引也可能有一些包含的列(在叶级页面中),并且有了这些,可以满足查询(所有请求的列都存在),因此您可以取回您要求的值

  • 或者你想要的值并不全部在非聚集索引叶级页面中(如果你一直这样做尤其如此SELECT *),然后查询执行器必须从非聚集索引中获取聚集键值,然后返回到聚簇索引,执行所谓的键查找,通过聚簇索引查找,并找到存储完整行的关联数据页 ->现在查询执行器可以返回您要求的值

要获得一个很好的解释 - 请在此处查看此博客文章。它说:

在非聚集索引中:
....
2.b。如果表具有聚集索引,或者索引位于索引视图上,则行定位器是该行的聚集索引键。SQL Server 通过使用存储在非聚集索引的叶子行中的聚集索引键来搜索聚集索引来检索数据行。

或者在 SQL Server 索引的整个系列中查看这篇博客文章,其中也解释了存储在非聚集索引叶级页面中的“书签”。

于 2012-08-31T09:11:45.837 回答
3

很容易想象这样:

您有一张客户表,例如客户(id、姓名、年龄、地址)。在这张表上,您有一个关于年龄的聚集索引。这意味着您的数据在硬盘驱动器上按年龄排序。当您想要进行范围查询时,这非常有用,例如:

SELECT * FROM customer WHERE age > 18;

然后,只需进行几次顺序读取,就可以从您的硬盘驱动器中获取数据。如果索引是非集群的,您将不得不为每个匹配的客户元组进行一次磁盘访问(包括数据的查找)。

也许对于您的应用程序,您还需要通过 id 访问用户。这意味着如果没有额外的 id 索引,您将不得不遍历整个文件才能找到特定的 id,因为它是按年龄排序的,而且您没有索引!为避免这种情况,您在 id 上创建第二个索引。现在您可以在此索引中搜索一个 id,并且包含您正在寻找的客户的索引的叶子指向您在磁盘上(按年龄聚集的)数据中找到元组的位置。这样你就不能读取整个表需要更少的磁盘访问(通常 2 用于索引查找 + 1 用于获取元组)。

编辑:我没有看到您在谈论同一专栏。我可以想象的一件事是,由于上述原因,您在一列上执行了一个聚集索引,例如,此列和另一列的另一个组合索引。这对于进行仅索引查找很有用,这里您在索引中拥有所有必需的属性,并且根本不需要进行页面获取。另一个原因是对于范围查询有一个聚集的 B+-Index,对于相等查询有一个 Hash-Index。但我认为这里的好处可以忽略不计。

希望这有帮助!

于 2013-02-18T16:49:38.367 回答