首页 文章

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

提问于
浏览
2

我在Stackoverflow中遇到了this帖子 . 第一个答案提到像 A clustered index has all the data for the table while a non clustered index only has the column + the location of the clustered index or the row if it is on a heap (a table without a clustered index). 非聚集索引如何具有聚集索引的位置?它只包含作为B树中的节点排序的列值,每个节点都固定到列具有该节点值的行,对吧?

2 回答

  • 3

    假设你正在谈论 SQL Server 并且还假设你的 table 上有一个聚集索引(你应该这样做) .

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

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

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

    • either 这个 Value 就是你所关心的 - 那么你只需要回到那个 Value

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

    • or 那么你想要的值并不都在非聚集索引叶级页面中(如果你一直都是 SELECT * 则尤其如此)然后查询 Actuator 必须从非聚簇索引中获取聚类键值,然后返回到聚类索引,执行所谓的键查找,搜索聚类索引,并找到存储完整行的关联数据页面 - >现在查询执行程序可以返回您要求的值

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

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

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

  • 4

    这很容易想象:

    您有一个客户表,例如客户(身份证,姓名,年龄,地址) . 在这张 table 上你有一个 clustered index 年龄 . 这意味着您的数据在硬盘驱动器上是 sorted by age . 当您想要进行范围查询时,这非常有用:

    SELECT * FROM customer WHERE age > 18;
    

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

    也许对于您的应用程序,您还需要通过id访问用户 . 这意味着如果没有id的附加索引,您将需要 run over the entire file 来查找特定ID,因为它按年龄排序而您没有索引!为避免这种情况,请创建 second index on id . 现在,您可以在此索引中搜索id,并且索引的叶子(包含您要查找的客户)指向光盘中(按年龄聚集)数据中的位置,您可以在其中找到元组 . 通过这种方式,您不必读取整个表需要更少的光盘访问(通常2用于索引查找1以获取元组) .

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

    希望这有帮助!

相关问题