pt-duplicate-key-checker
这是搜索冗余索引的 Percona 工具的输出片段:
# Key myidx ends with a prefix of the clustered index
# Key definitions:
# KEY `myidx` (`bar`,`foo`)
# PRIMARY KEY (`foo`),
# Column types:
# `bar` mediumint(8) unsigned not null default '0'
# `foo` mediumint(8) unsigned not null auto_increment
# To shorten this duplicate clustered index, execute:
ALTER TABLE `mydb`.`mytable` DROP INDEX `myidx`, ADD INDEX `myidx` (`bar`);
为什么该工具会提示这个?原来的复合索引就不能用了吗?
据我了解,bar
给定 PK 上的索引值得删除(bar,foo)
,但这里并非如此。
主键是 InnoDB 中任何辅助键的一部分。
我不同意该工具给出的分析。
当我看到 时
INDEX(bar, foo)
,我假设有一些查询需要这两列按此顺序位于此复合索引中。foo
PK 与INDEX(bar)
上述指标相同的事实无关紧要。当我看到 just
INDEX(bar)
时,我假设有一些查询(bar)
不需要id
.当我看到两者时,我会说较短的是“多余的”并建议将其删除。
此外,“缩短这个重复的聚集索引”是错误的。
INDEX(bar)
不比INDEX(bar, foo)
. 而且它不是“聚集索引”。只有PK是“聚集的”。如果是
UNIQUE(bar, foo)
,那么我会建议更改UNIQUE
为INDEX
. 这样就INSERTs
不必进行不必要的唯一性检查。让我们创建一个简单的表,看看 MySQL(5.7.20 MySQL 社区服务器)必须告诉我们什么:
这是一个可以从索引中读取的简单查询:
这表明密钥条已被使用并且有 2 个密钥部分,都被读取以产生长度为 8 (2x4) 的密钥。现在让我们切换单个字段的复合键并再次检查:
现在只有关键部分和长度发生了变化,这是符合预期的,但它仍然是一个索引读取。如果我们将其转换为对 PK 字段的范围查询,并对索引字段进行约束,让我们看看会发生什么:
查询规划器已经考虑了查询的 PK,但选择了 的索引
bar
,它现在对之前读取的索引有一个有趣的变化,因为我们可以看到它现在再次显示为 2 个关键部分,长度为 8:这告诉我们MySQL已经访问了自动包含在二级索引中的PK