而 uniq 表比原表小的多,这就是因为不再需要那个 `隐式的自增 id 字段作为主键`
回到`SELECT * FROM tag_content_rel WHERE content_id = 50000`本身,他的 EXPLAIN 是
Using index for skip scan 意味着查询计划是将 key (这里是 PK )用于帮助加快 full table scan 的速度,因为根据 key 中的信息可以知道有些行可以直接跳过(所以叫 skip scan ),但这并不能改变查询计划仍然是在做 full table scan 的罪恶本质:
https://dev.mysql.com/doc/refman/8.0/en/range-optimization.html而只能 full table scan 的根本原因是这个 sql 的 where 子句只有对字段 content_id 的约束,而 content_id 不在任何索引的最左字段(第一个)之中,因为您的 PK 是(tag_id, content_id)而不是(content_id, tag_id)
所以在
ALTER TABLE `tag_content_rel_uniq` ADD INDEX(`content_id`)
之后
立省 50%
EXPLAIN 显示这下的确是直接使用了新建的 content_id 索引,所以不再需要任何形式的 full table scan 了:
但代价是这个新索引吃了 148mb 空间(加了之后我还没 OPTIMIZE TABLE ),但整个表大小 460 也小于您最初设计的表 604
如果您需要节省空间(既是指硬盘上的空间也是指 innodb buffer pool 中能塞下多少个这样大的表的 index )
那么需要根据您实际业务的查询,您是主要查询 WHERE content_id 还是 WHERE tag_id (都只约束一个字段,如果两个字段都约束那肯定会用上 composite key ,因为您的 CK 只有这两个字段),就把哪个字段移动到现有 CK (在这里是 PK )的最左(第一个)