为什么 InnoDB 表默认使用 UNIQUE 约束而不是 PRIMARY KEY?

Aid*_*api 5 mysql primary-key mysql-5.6 unique-constraint

在我的 MySQL 数据库中,我有一个包含 4 列的表,其中PRIMRAY KEY两列带有FOREIGN KEY CONSTRAINT一个UNIQUE 索引和一个索引,除了PRIMARY KEY.

SHOW CREATE TABLE

CREATE TABLE `zdb_userbeschikbaarheid` (
  `UserBeschikbaarheid_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `UB_User_ID` int(10) unsigned NOT NULL,
  `UB_PlanDagdeelTaak_ID` int(10) unsigned NOT NULL,
  `UB_Datum` date NOT NULL,
  PRIMARY KEY (`UserBeschikbaarheid_ID`),
  UNIQUE KEY `UQ_UB_User_ID_PlanDagdeelTaak_ID_Datum` (`UB_Datum`,`UB_User_ID`,`UB_PlanDagdeelTaak_ID`),
  KEY `FK_UB_User_ID` (`UB_User_ID`),
  KEY `FK_UB_PlanDagdeelTaak_ID` (`UB_PlanDagdeelTaak_ID`),
  CONSTRAINT `FK_UB_PlanDagdeelTaak_ID` FOREIGN KEY (`UB_PlanDagdeelTaak_ID`) REFERENCES `zdb_plandagdeeltaak` (`PlanDagdeelTaak_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_UB_User_ID` FOREIGN KEY (`UB_User_ID`) REFERENCES `zdb_user` (`User_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=522 DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)

由于某些奇怪的原因,当我选择完整表时,它使用UNIQUE索引而不是PRIMARY KEY. 一个EXPLAIN SELECT * FROM zdb_userbeschikbaarheid;收益率:

id  select_type table                   type    possible_keys   
1   SIMPLE      zdb_userbeschikbaarheid index   \N

key                                     key_len ref rows    Extra
UQ_UB_User_ID_PlanDagdeelTaak_ID_Datum  11      \N  415     Using index
Run Code Online (Sandbox Code Playgroud)

PRIMARY KEY直到我专门告诉ORDER BY主键它才会使用。
EXPLAIN SELECT * FROM zdb_userbeschikbaarheid ORDER BY UserBeschikbaarheid_ID;

id  select_type table                   type    possible_keys
1   SIMPLE      zdb_userbeschikbaarheid index   \N

key     key_len ref rows    Extra
PRIMARY 4       \N  415     \N
Run Code Online (Sandbox Code Playgroud)

UNIQUE KEY选择 而不是似乎很奇怪PRIMARY KEY

是什么导致了这种行为,它是我的数据库的潜在问题吗?如果可能,我该如何更改它以使用PRIMARY KEY默认值?

ype*_*eᵀᴹ 8

对于 InnoDB 表,所有二级索引都包含聚集索引(即主键)的列,并附加在末尾。所以你的唯一索引实际上有 4 列,你定义的 3 列加上 1 个主键列。

当运行需要全表扫描的查询时,两个索引都拥有所需的所有数据,因此优化器可以自由选择两个索引中的任何一个。事实上,如InnoDB 表和索引结构中所述,聚集索引包含一些额外的信息,每行多花费 13 个字节:

聚集索引中的记录包含所有用户定义列的字段。此外,还有一个 6 字节的事务 ID 字段和一个 7 字节的滚动指针字段。

这使您的唯一索引比主键索引更窄,这就是优化器选择它的原因。