我对DB的接触有限,只是作为应用程序程序员使用过DB。我想知道关于聚集和非聚集索引。 我在谷歌上搜索了一下,我发现:

A clustered index is a special type of index that reorders the way records in the table are physically stored. Therefore table can have only one clustered index. The leaf nodes of a clustered index contain the data pages. A nonclustered index is a special type of index in which the logical order of the index does not match the physical stored order of the rows on disk. The leaf node of a nonclustered index does not consist of the data pages. Instead, the leaf nodes contain index rows.

我在SO中发现的是聚集索引和非聚集索引之间的区别是什么?

有人能用通俗易懂的语言解释一下吗?


当前回答

我知道这是一个非常古老的问题,但我想我可以提供一个类比来帮助说明上面的答案。

聚集索引

If you walk into a public library, you will find that the books are all arranged in a particular order (most likely the Dewey Decimal System, or DDS). This corresponds to the "clustered index" of the books. If the DDS# for the book you want was 005.7565 F736s, you would start by locating the row of bookshelves that is labeled 001-099 or something like that. (This endcap sign at the end of the stack corresponds to an "intermediate node" in the index.) Eventually you would drill down to the specific shelf labelled 005.7450 - 005.7600, then you would scan until you found the book with the specified DDS#, and at that point you have found your book.

非聚簇索引

But if you didn't come into the library with the DDS# of your book memorized, then you would need a second index to assist you. In the olden days you would find at the front of the library a wonderful bureau of drawers known as the "Card Catalog". In it were thousands of 3x5 cards -- one for each book, sorted in alphabetical order (by title, perhaps). This corresponds to the "non-clustered index". These card catalogs were organized in a hierarchical structure, so that each drawer would be labeled with the range of cards it contained (Ka - Kl, for example; i.e., the "intermediate node"). Once again, you would drill in until you found your book, but in this case, once you have found it (i.e, the "leaf node"), you don't have the book itself, but just a card with an index number (the DDS#) with which you could find the actual book in the clustered index.

当然,没有什么能阻止图书管理员复印所有的卡片,并将它们按不同的顺序分类在一个单独的卡片目录中。(通常至少有两个这样的目录:一个按作者姓名排序,另一个按标题排序。)原则上,您可以拥有任意数量的这些“非聚集”索引。

其他回答

聚集索引意味着您告诉数据库在磁盘上存储实际上彼此接近的接近值。这样做的好处是可以快速扫描/检索某些聚集索引值范围内的记录。

例如,你有两个表,Customer和Order:

Customer
----------
ID
Name
Address

Order
----------
ID
CustomerID
Price

如果希望快速检索某个特定客户的所有订单,则可能希望在订单表的“CustomerID”列上创建聚集索引。这样,具有相同CustomerID的记录将在物理上彼此靠近地存储在磁盘上(集群),从而加快了它们的检索速度。

附注:CustomerID上的索引显然不是唯一的,因此您要么需要添加第二个字段来“唯一”索引,要么让数据库为您处理,但这是另一回事。

Regarding multiple indexes. You can have only one clustered index per table because this defines how the data is physically arranged. If you wish an analogy, imagine a big room with many tables in it. You can either put these tables to form several rows or pull them all together to form a big conference table, but not both ways at the same time. A table can have other indexes, they will then point to the entries in the clustered index which in its turn will finally say where to find the actual data.

聚集索引

聚集索引根据表或视图中的键值对数据行进行排序和存储。这些是包含在索引定义中的列。每个表只能有一个聚集索引,因为数据行本身只能按一种顺序排序。

只有当表中包含聚集索引时,表中的数据行才会按排序顺序存储。当一个表具有聚集索引时,这个表称为聚集表。如果表没有聚集索引,则其数据行存储在称为堆的无序结构中。

非聚集

Nonclustered indexes have a structure separate from the data rows. A nonclustered index contains the nonclustered index key values and each key value entry has a pointer to the data row that contains the key value. The pointer from an index row in a nonclustered index to a data row is called a row locator. The structure of the row locator depends on whether the data pages are stored in a heap or a clustered table. For a heap, a row locator is a pointer to the row. For a clustered table, the row locator is the clustered index key.

可以将非键列添加到非聚集索引的叶级,以绕过现有的索引键限制,并执行完全覆盖的索引查询。有关更多信息,请参见创建包含列的索引。有关索引键限制的详细信息,请参见SQL Server最大容量规格。

参考:https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described

下面是聚类索引和非聚类索引的一些特征:

聚集索引

聚集索引是唯一标识SQL表中的行的索引。 每个表只能有一个聚集索引。 可以创建包含多个列的聚集索引。例如:create Index index_name(col1, col2, col.....)。 默认情况下,具有主键的列已经具有聚集索引。

非聚簇索引

非聚集索引类似于简单索引。它们只是用于快速检索数据。不一定有唯一的数据。

聚集索引

聚集索引基本上是一个树状组织的表。与将记录存储在未排序的Heap表空间中不同,聚集索引实际上是具有叶子节点(按群集键列值排序)的B+树索引,存储实际的表记录,如下图所示。

在SQL Server和MySQL中,Clustered Index是默认的表结构。即使表没有主键,MySQL也会添加一个隐藏的集群索引,而SQL Server总是在表有主键列时构建一个集群索引。否则,SQL Server将存储为堆表。

聚集索引可以加速按聚集索引键过滤记录的查询,就像通常的CRUD语句一样。由于记录位于叶节点中,因此在根据记录的Primary Key值定位记录时,不需要额外查找额外的列值。

例如,在SQL Server上执行如下SQL查询:

SELECT PostId, Title
FROM Post
WHERE PostId = ? 

您可以看到,执行计划使用群集索引查找操作来定位包含Post记录的叶子节点,并且扫描群集索引节点只需要两个逻辑读取:

|StmtText                                                                             |
|-------------------------------------------------------------------------------------|
|SELECT PostId, Title FROM Post WHERE PostId = @P0                                    |
|  |--Clustered Index Seek(OBJECT:([high_performance_sql].[dbo].[Post].[PK_Post_Id]), |
|     SEEK:([high_performance_sql].[dbo].[Post].[PostID]=[@P0]) ORDERED FORWARD)      | 

Table 'Post'. Scan count 0, logical reads 2, physical reads 0

非聚簇索引

由于聚集索引通常是使用主键列值构建的,如果您想加快使用其他列的查询速度,那么必须添加次要非聚集索引。

二级索引将在它的叶节点中存储主键值,如下图所示:

因此,如果我们在Post表的Title列上创建一个Secondary Index:

CREATE INDEX IDX_Post_Title on Post (Title)

然后执行下面的SQL查询:

SELECT PostId, Title
FROM Post
WHERE Title = ? 

我们可以看到,索引查找操作用于在IDX_Post_Title索引中定位叶子节点,它可以提供我们感兴趣的SQL查询投影:

|StmtText                                                                      |
|------------------------------------------------------------------------------|
|SELECT PostId, Title FROM Post WHERE Title = @P0                              |
|  |--Index Seek(OBJECT:([high_performance_sql].[dbo].[Post].[IDX_Post_Title]),|
|     SEEK:([high_performance_sql].[dbo].[Post].[Title]=[@P0]) ORDERED FORWARD)|

Table 'Post'. Scan count 1, logical reads 2, physical reads 0

由于相关的PostId主键列值存储在IDX_Post_Title叶节点中,因此此查询不需要额外查找来定位聚集索引中的Post行。

我知道这是一个非常古老的问题,但我想我可以提供一个类比来帮助说明上面的答案。

聚集索引

If you walk into a public library, you will find that the books are all arranged in a particular order (most likely the Dewey Decimal System, or DDS). This corresponds to the "clustered index" of the books. If the DDS# for the book you want was 005.7565 F736s, you would start by locating the row of bookshelves that is labeled 001-099 or something like that. (This endcap sign at the end of the stack corresponds to an "intermediate node" in the index.) Eventually you would drill down to the specific shelf labelled 005.7450 - 005.7600, then you would scan until you found the book with the specified DDS#, and at that point you have found your book.

非聚簇索引

But if you didn't come into the library with the DDS# of your book memorized, then you would need a second index to assist you. In the olden days you would find at the front of the library a wonderful bureau of drawers known as the "Card Catalog". In it were thousands of 3x5 cards -- one for each book, sorted in alphabetical order (by title, perhaps). This corresponds to the "non-clustered index". These card catalogs were organized in a hierarchical structure, so that each drawer would be labeled with the range of cards it contained (Ka - Kl, for example; i.e., the "intermediate node"). Once again, you would drill in until you found your book, but in this case, once you have found it (i.e, the "leaf node"), you don't have the book itself, but just a card with an index number (the DDS#) with which you could find the actual book in the clustered index.

当然,没有什么能阻止图书管理员复印所有的卡片,并将它们按不同的顺序分类在一个单独的卡片目录中。(通常至少有两个这样的目录:一个按作者姓名排序,另一个按标题排序。)原则上,您可以拥有任意数量的这些“非聚集”索引。