一尘不染

具有复合索引但不具有主键的MySQL表

mysql

我需要一个表来存储一些评分,在此表中,我有一个 综合索引(user_id,post_id) 和其他列来标识不同的评分系统。

user_id - bigint
post_id - bigint
type - varchar
...

Composite Index (user_id, post_id)

在此表中,我没有 主键, 因为 主键 必须是唯一的,而INDEX不必是唯一的,就我而言,唯一性是一个问题。

例如我可以有

INSERT INTO tbl_rate
    (user_id,post_id,type)
VALUES
    (24,1234,'like'),
    (24,1234,'love'),
    (24,1234,'other');

缺少PRIMARY KEY可能会导致性能问题?我的表结构好还是需要更改?

谢谢


阅读 326

收藏
2020-05-17

共1个答案

一尘不染

几点:

听起来您只是在使用表的当前唯一特性,并将其用作主键。那个有效。由于本地性,自然键在查询方面具有一些优势。(每个用户的数据存储在同一区域中)。而且由于该表是由该键聚集的,因此,如果您按主键中的列进行搜索,则可以消除对数据的查找。

  1. 但是,使用您选择的自然主键对性能也有不利影响。

  2. 使用非常大的主键会使innodb中的所有其他索引变得非常大,因为主索引包含在每个索引值中。

  3. 使用自然主键的速度不如INSERT的替代键快,因为除了更大以外,它还不能每次都插入表的末尾。它必须在该用户的部分中插入并发布等。

  4. 另外,如果您按时间进行搜索,除非时间是第一列,否则您将使用自然键在整个表中进行搜索。代理键在时间上往往是本地的,对于某些查询通常可能恰好是正确的。

  5. 使用像您这样的自然键作为主键也很烦人。如果您想提及特定的选票怎么办?您需要一些字段。而且,与许多ORM一起使用时有点困难。

这是答案

我将创建自己的代理键并将其用作主键,而不是依赖innodb的内部主键,因为您将能够使用它进行更新和查找。

ALTER TABLE tbl_rate 
ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT, 
ADD PRIMARY KEY(id);

但是,如果您确实创建了代理主键,那么我还将使您的键成为唯一键。相同的成本,但可以确保正确性。

ALTER TABLE tbl_rate 
ADD UNIQUE ( user_id, post_id, type );
2020-05-17