SQL 服务器中的聚集索引:列在模式中排在第一位有什么好处?

Clustered index in SQL Server : any advantage for the columns to be first in schema?

我在 SQL 服务器中有一个 table 具有三列聚集索引。

我有一个包含列 (CustomerID, A, ProductID, C, OtherID) 的 table 并且我在 (OtherID, CustomerID, ProductID) 上有一个聚集键。

该列顺序是否会影响性能(在 table 中,而不是在索引中?)或者将键列重新排序到 [= 的前三列是否有隐藏的优势26=]: (OtherID,CustomerID,ProductID,A,C)

看起来这应该不是什么大问题,但实现可能会有隐藏的性能成本。

(我正在寻找我们遇到的性能问题的原因,这只是其中之一“它 不应该 是一个问题,但也许它可以成为一个问题...”的猜测。)

我不会假设我们在这里讨论的是什么类型的聚簇索引,所以我将尝试涵盖所有基础知识。我不得不说,逻辑上,table 中列的序号位置相对于它们在聚簇索引中的序号位置的影响(性能或其他方面)无关紧要(除非有人证明我错了)。

行存储

请记住,您的 table 数据和行存储聚集索引最终会成为独立的逻辑结构。 Per Microsoft regarding the clustered rowstore index architecture:

indexes are organized as B-Trees. Each page in an index B-tree is called an index node. The top node of the B-tree is called the root node. The bottom nodes in the index are called the leaf nodes. Any index levels between the root and the leaf nodes are collectively known as intermediate levels. In a clustered index, the leaf nodes contain the data pages of the underlying table. The root and intermediate level nodes contain index pages holding index rows.

所以当我们谈论聚集索引和table数据的物理存储时,我们可以将它们视为单独的结构。从同一张 link 看这张图片:

所有这三个级别至少有一个共同点。它们都存储值(或多或少)按聚集索引的值进行逻辑排序。无论 table 结构中列的序号位置如何,table 数据的叶页都将按 columns/values 逻辑顺序存储在聚簇索引中。这也适用于您的中间页面,它代表您的聚簇索引值的存储。

综上所述,聚集索引中列的顺序位置实际上决定了中间层和叶页的逻辑排序方式,因此这些列在 table 语句实际上对它们的存储顺序没有影响,因为它们包含在您的聚集索引中。

列存储

关于聚集列存储索引,我再次声明它没有影响,但出于不同(且更简单)的原因。列存储索引将列值分解为单独的逻辑结构,这些逻辑结构在顺序位置方面彼此没有关系。因此,无论列在 table 中的序号位置如何,当您从列中查询值时,您查询的是表示该列值的单独物理结构(为简单起见,此处忽略增量存储)。同样,当您查询多个列的值时,您正在查询分别代表每个列的值的每个单独的逻辑结构。

这就是为什么您在 creating a clustered columnstore index 时甚至无法指定列列表的原因。 columnstore 索引本身中列的顺序位置没有影响,所以我想这些列在 table 本身(或两者之间的任何关系)中的顺序位置也没有影响。

最后,如果有人问,即使 table 存储为堆,我仍然认为 table 中列的顺序位置对任何查询性能没有影响。在幕后,堆仍然由一种聚集索引结构存储和引用(我相信它仍然会被这样描述)。

Per Microsoft:

A rowstore is data that is logically organized as a table with rows and columns, and then physically stored in a row-wise data format. This has been the traditional way to store relational table data such as a heap or clustered B-tree index.

因此,堆仍然以有序方式存储,就像使用聚集索引创建的任何其他 table 一样,但主要区别在于,它们排序所依据的值只是在创建的非业务使用值顺序来识别行。 As described by Microsoft:

If the table is a heap, which means it does not have a clustered index, the row locator is a pointer to the row. The pointer is built from the file identifier (ID), page number, and number of the row on the page. The whole pointer is known as a Row ID (RID).

您通常不会将此 RID 用作查询的谓词,这是主要缺点(因为数据是用来查询的,对吧?)。但无论如何,这些列在 table 中的顺序位置仍然不会影响它们在逻辑上的实际位置 sorted/stored,因此我无法想象它会影响您的查询性能。