【发布时间】:2021-02-19 10:43:55
【问题描述】:
我有一个非常大的表(> 60 亿行 & > 3tb 的数据),我正在尝试更改。
示例架构:
CREATE TABLE `huge_table` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`col1` int(11) unsigned DEFAULT NULL,
`col2` int(11) unsigned DEFAULT NULL,
`col3` int(11) unsigned NOT NULL,
`col4` int(11) unsigned DEFAULT NULL,
`col5` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`col6` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`col7` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`col8` datetime GENERATED ALWAYS AS (cast(`created` as date)) VIRTUAL,
`dt1` timestamp(3) NULL DEFAULT NULL,
`dt2` timestamp(3) NULL DEFAULT NULL,
`dt3` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (`id`),
UNIQUE KEY `idx_col5` (`col5`),
KEY `col4` (`col4`),
KEY `col1` (`col1`),
KEY `col3` (`col3`),
KEY `col6` (`col6`,`col3`),
KEY `col2` (`col2`),
KEY `col8` (`col8`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
这些索引中的大多数都是不必要的,所以我正在尝试清理它们,并添加更精确的索引。请注意,下面的所有ALTER TABLE 语句都需要超过 24 小时才能运行。
首先,我尝试使用 Online DDL 修改所有索引:
ALTER TABLE huge_table
DROP INDEX col4_idx,
DROP INDEX col1_idx,
DROP INDEX col3_idx,
DROP INDEX col6_idx,
DROP INDEX col2_idx,
DROP INDEX col8_idx,
ADD INDEX new_idx(col3, col6, col1),
ALGORITHM=INPLACE, LOCK=NONE;
当这最终完成时(没有错误),我检查了架构,却发现架构中没有任何变化。因此,我决定不强制它运行“INPLACE”再试一次:
ALTER TABLE huge_table
DROP INDEX col4_idx,
DROP INDEX col1_idx,
DROP INDEX col3_idx,
DROP INDEX col6_idx,
DROP INDEX col2_idx,
DROP INDEX col8_idx,
ADD INDEX new_idx(col3, col6, col1);
这也不起作用(它似乎仍在在线模式下运行)。我决定将这个过程分成两部分:首先删除不必要的列,然后添加新列:
ALTER TABLE huge_table
DROP INDEX col4_idx,
DROP INDEX col1_idx,
DROP INDEX col3_idx,
DROP INDEX col6_idx,
DROP INDEX col2_idx,
DROP INDEX col8_idx;
ALTER TABLE huge_table
ADD INDEX new_idx(col3, col6, col1);
删除列只用了几秒钟,新索引完成且没有错误(再次,在联机模式下)。不幸的是,新索引没有采用。
我认为整个 DDL 语句在创建新索引失败后最终被回滚,但没有看到任何记录;它似乎默默地失败了。我想知道是不是因为有一个VIRTUAL 列,但我希望引擎会返回某种错误消息。有没有其他人看到过这种类型的问题?
【问题讨论】: