14

我正在阅读有关聚集索引如何工作的所有内容,并认为它们对我的应用程序有益。我知道主键是自动聚集索引,但是如何将聚集索引添加到非主键列?

即用户帖子的数据存储。每个帖子都有一个ID,也有一个user-id,但是由于用户可以多次发帖,所以user-id不是主键。您将如何将聚集索引添加到用户 ID,这甚至是一个好主意吗?

4

4 回答 4

22

根据Clustered and Secondary Indexes,每个表只能有一个聚集索引。

除聚集索引外的所有索引都称为二级索引。

如果一个表没有主索引但有另一个唯一索引,则将其用作聚集索引。

如果你没有为你的表定义 PRIMARY KEY,MySQL 会定位第一个唯一索引,其中所有键列都不是 NULL,InnoDB 将它用作聚集索引。

因此,我会得出结论,您自己不会添加聚集索引,但 MySQL 会选择表的主索引或第一个唯一索引作为聚集索引。


如果您尚未定义主索引或唯一索引,MySQL 会自行创建索引

如果 table 没有 PRIMARY KEY 或合适的 UNIQUE 索引,InnoDB 在内部生成一个名为 GEN_CLUST_INDEX 的隐藏聚集索引,该索引包含行 ID 值的合成列。这些行按 InnoDB 分配给此类表中的行的 ID 排序。行 ID 是一个 6 字节的字段,随着新行的插入而单调增加。因此,按行 ID 排序的行在物理上是按插入顺序排列的。

于 2012-12-08T17:34:46.680 回答
9

As @Olaf describes, InnoDB chooses which column or column combination will be the clustered index (the primary key, or the first unique index if there is not a primary key, or a hidden column if there is none of the two).

If you want to have a non-unique column as the clustered index, you could define the post_id as a unique key and make the combination of user_id and post_id the primary key which will be chosen as the clustered index:

CREATE TABLE Post
( post_id INT NOT NULL AUTO_INCREMENT
, user_id INT NOT NULL
--- other columns
, CONSTRAINT Post_PK
    PRIMARY KEY (user_id, post_id)     -- your clustered index
, CONSTRAINT post_id_UQ
    UNIQUE (post_id)             -- you still want uniqueness for the `post_id`
) ENGINE = InnoDB ;

Whether this is a good idea or not depends on your application, the data volumes and the queries you have. In general the best properties of a clustered key are unique, narrow, static and ever-increasing. That's why auto-incrementing columns are best. Read about it in Kimberly L. Tripp's blog articles: Ever-increasing clustering key - the Clustered Index Debate..........again! and The Clustered Index Debate Continues... (don't stop because they are for SQL-Server, the same issues apply 99% to InnoDB's clustered indexing)

A clustered key like the (user_id, post_id) has the first 3 properties but it is not ever-increasing. This will result in fragmentation of the CI and possibly slower insertions into the table.

It will however result in more efficient queries that have WHERE user_id = ? conditions or range conditions WHERE user_id BETWEEN ? AND ? or GROUP BY user_id groupings as the wanted data will be found in the clustered index in one place and in the required order.

I suggest you make tests to choose which is best in your case.


There is also a MySQL variant, TokuDB, that allows multiple clustered indexes in a table. Details in their article: Introducing Multiple Clustering Indexes

于 2012-12-08T17:45:38.013 回答
3

当您为 InnoDB 表定义主键时,MySQL 使用主键作为聚集索引。

如果您没有表的主键,MySQL 将搜索所有键列都不是 NULL的第一个UNIQUE 索引,并将此 UNIQUE 索引用作聚集索引。

如果 InnoDB 表没有主键或合适的 UNIQUE 索引,MySQL会在包含行 ID 值的合成列上内部生成一个名为GEN_CLUST_INDEX的隐藏聚集索引。

于 2019-06-27T06:48:16.633 回答
1

我建议你问错问题。

另一个问题是“我可以摆脱我的电流PRIMARY KEY,这样我就可以让另一个东西‘聚集’吗?” 通常一个AUTO_INCREMENT可以被消除或变成一个简单的INDEX

更有可能的问题是“什么是最佳索引SELECT ...?”。其他人指出,对于基本的 MySQL,第二个聚集索引是不可能的,那么下一个选择是什么?我无法在不知道的情况下回答这个问题SELECT。然而,我的 Index Cookbook回答了一大堆问题SELECTs

于 2015-11-26T07:36:15.293 回答