同一列上的非聚集索引和聚簇索引

时间:2012-08-31 09:05:58

标签: sql-server indexing b-tree clustered-index non-clustered-index

我在Stackoverflow中发现了this帖子。第一个答案提到类似聚簇索引具有表的所有数据,而非聚簇索引仅具有列+聚簇索引的位置或行(如果它在堆上)(没有聚簇的表) index)。非聚集索引如何具有聚簇索引的位置?它只包含作为B树中节点排序的列值,每个节点都固定到列具有该节点值的行,对吧?

2 个答案:

答案 0 :(得分:4)

假设您正在谈论 SQL Server ,并假设您在您的桌面上拥有聚集索引(正如您所希望的那样)。

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

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

如果查询执行程序通过非聚集索引查找值并找到匹配项,那么

  • 这个价值就是您所关心的 - 然后您只需返回该值

  • 非聚集索引也可能包含一些包含列(在叶级页面中)以及那些查询可以满足(请求的所有列都存在),以便您获得所需的值

  • 然后您想要的值不在非聚集索引叶级页面中(如果您执行SELECT *所有这一切尤其如此时间)然后查询执行器必须从非聚集索引中获取聚类键值,然后返回聚类索引,执行所谓的键查找,搜索聚类索引,并查找存储完整行的关联数据页面 - >和现在查询执行者可以返回您要求的值

有一个很好的解释 - 见this blog post here。它说:

  

在NonClustered Index中:
  ....
  2.B.如果表具有Clustered索引,或索引位于Indexed视图上,则行定位器是该行的Clustered index Key。 SQL   服务器通过使用搜索聚簇索引来检索数据行   Clustered index Key存储在NonClustered的Leaf行中   索引。

或者参见this blog post in a whole series on SQL Server indexes,它解释了存储在非聚集索引叶级页面中的“书签”。

答案 1 :(得分:3)

很容易想象这样:

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

SELECT * FROM customer WHERE age > 18;

然后只需几次连续读取即可从硬盘中获取数据。如果索引是非聚集的,则必须为每个匹配的客户元组进行一次磁盘访问(包括查找数据)。

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

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

希望这有帮助!