据我所知,聚集索引创建一个B树,实际数据存储在作为双向链表连接的树叶中。SQL服务器中聚簇索引扫描期间读取的实际表数据还是索引指针?
但是,如果存在索引扫描(从表中选择没有任何“where”子句的数据),那么SQL服务器是只读取索引指针(非叶节点)还是实际读取数据?
我的执行计划显示聚集索引扫描得到1 GB的数据,这与我的表大小几乎相同。根据我的理解,SQL索引扫描应该获取所有实际的表数据。我在这里错过了什么。
据我所知,聚集索引创建一个B树,实际数据存储在作为双向链表连接的树叶中。SQL服务器中聚簇索引扫描期间读取的实际表数据还是索引指针?
但是,如果存在索引扫描(从表中选择没有任何“where”子句的数据),那么SQL服务器是只读取索引指针(非叶节点)还是实际读取数据?
我的执行计划显示聚集索引扫描得到1 GB的数据,这与我的表大小几乎相同。根据我的理解,SQL索引扫描应该获取所有实际的表数据。我在这里错过了什么。
聚集索引本身是表,所以表read..Index指针只是用于通过B树导航
聚集索引本身是实际的表...
如果直接创建一个表没有聚集索引,它被称为堆 - 这只是一些无组织(无序)的页面集。每个页面将指向前一页和下一页(双向链接列表)。
现在想象你该表创建一个聚集索引:现在
所有页面都存储在集群中指定的键的顺序 - >这些都是叶级页,并包含每一行中的实际数据。这些仍然使用双向链表。
此外,聚集索引结构将涉及上层的额外页面(可能超过一个层次),以便它们形成平衡树 - >这些是分支页面和根页面。仅从聚簇键获得的数据用作指向较低级别页面的指针。
这种形式使得SQL引擎可以容易地找到找到数据所需的页面(被称为SEEK操作),例如当您执行使用与集群密钥匹配的谓词的查询时,它将能够有效地查找确切的数据。
如果键不匹配,或者SQL知道该表足够小(或者即使它知道它几乎返回了整个表数据),也不必使用上层页面。它可能会决定直接进入叶级页面来扫描所有行并找出匹配的记录。记住双链表以指向上一页和下一页。
Bonus:即使指定了WHERE子句,也可能存在索引扫描,因为它无法使用seek或SQL思想,因此扫描的效率高于seek。
让我知道这是否有帮助。