我正在阅读关于聚簇索引如何工作的所有内容,并认为它们对我的应用程序有益。我知道主键是自动聚簇索引,但是如何将聚簇索引添加到非主键列?
即。用户帖子的数据存储区。每个帖子都有一个ID,但也有一个用户ID,但由于用户可以多次发帖,因此user-id不是主键。如何将聚集索引添加到用户ID,这甚至是个好主意?
答案 0 :(得分:16)
根据Clustered and Secondary Indexes,每个表只能有一个聚簇索引。
聚簇索引以外的所有索引都称为辅助索引。
如果表没有主索引而是另一个唯一索引,则将其用作聚簇索引。
如果没有为表定义PRIMARY KEY,MySQL会找到第一个UNIQUE索引,其中所有键列都是NOT NULL,而InnoDB将它用作聚簇索引。
因此,我得出结论,您不会自己添加聚簇索引,但MySQL会选择表的主要或第一个唯一索引作为聚簇索引。
答案 1 :(得分:8)
正如@Olaf描述的那样,InnoDB选择哪个列或列组合将成为聚簇索引(主键,如果没有主键,则为第一个唯一索引;如果两个都没有,则选择隐藏列) 。
如果您希望将非唯一列作为聚簇索引,则可以将post_id
定义为唯一键,并将user_id
和post_id
组合为主键将被选为聚集索引:
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 ;
这是否是一个好主意取决于您的应用程序,数据量和您拥有的查询。通常,群集密钥的最佳属性是唯一的,窄的,静态的和不断增加的。这就是为什么自动递增列最好的原因。在Kimberly L. Tripp的博客文章中了解它:Ever-increasing clustering key - the Clustered Index Debate..........again!和The Clustered Index Debate Continues...(不要停止,因为它们适用于SQL-Server,同样的问题适用于InnoDB的聚集索引99%)
像(user_id, post_id)
这样的聚类键具有前3个属性,但它不会增加。这将导致CI碎片化,并可能更慢地插入表中。
然而,它会产生更有效的查询,这些查询具有WHERE user_id = ?
条件或范围条件WHERE user_id BETWEEN ? AND ?
或GROUP BY user_id
分组,因为所需数据将在聚集索引中的某个位置找到所需的订单。
我建议您进行测试,以选择最适合您的情况。
还有一个MySQL变体TokuDB,允许在表中使用多个聚簇索引。文章中的详细信息: Introducing Multiple Clustering Indexes
答案 2 :(得分:1)
我建议你提出错误的问题。
另一个问题是"我可以摆脱目前的PRIMARY KEY
,这样我就能做出另一件事了#39;群集'?"通常AUTO_INCREMENT
可以被删除或变成简单的INDEX
。
更可能的问题是"这个SELECT ...
的最佳索引是什么?"。其他人指出,对于基本的MySQL,第二个聚簇索引是不可能的,那么下一个选择是什么?在不知道SELECT
的情况下,我无法回答这个问题。但是,my Index Cookbook回答了大量SELECTs
的问题。
答案 3 :(得分:0)
当您为InnoDB表定义主键时,MySQL使用主键作为聚簇索引。
如果您没有表的主键,则MySQL将搜索第一个 UNIQUE索引,其中所有键列都不为空,并将此UNIQUE索引用作聚集索引。
>如果InnoDB表没有主键或合适的UNIQUE索引,MySQL会在包含行ID值的综合列上内部生成一个名为 GEN_CLUST_INDEX 的隐藏的聚集索引。