节流ALTER TABLE磁盘利用率

Aev*_*eus 10 mysql database indexing alter-table

我将从MySQL 在线DDL限制页面开始:

没有机制可以暂停联机DDL操作或限制联机DDL操作的I/O或CPU使用率.

但是,我仍然对我可能错过的解决方案感兴趣.

情况:索引越来越大,而且它们变得越来越大,以至于没有足够的内存用于所使用的查询,导致磁盘I/O飙升,一切都陷入混乱.已经创建了较小的新复合索引,但问题是在ALTER TABLE不破坏任何内容的情况下运行.

事实如下:

  1. 这是一个InnoDB表.
  2. 该表没有主键或唯一索引.
  3. 没有列的组合适合作为主键或唯一索引.
  4. 该表没有外键.
  5. 该表每月分区(目前为50).
  6. 该表必须始终接受写入.
  7. 最新的3-6分区必须接受读取.
  8. 有一id列,但这不是唯一的.
  9. 该表包含大约20亿行.
  10. 当前月份的分区是唯一接收写入的分区.
  11. 分区是提前一个月提出的; 总有一个空分区.

SHOW CREATE TABLE(我没有包括所有分区):

CREATE TABLE `my_wonky_table` (
  `id` bigint(20) unsigned NOT NULL,
  `login` varchar(127) DEFAULT NULL,
  `timestamp` int(10) unsigned NOT NULL,
  `ip` varchar(32) CHARACTER SET ascii DEFAULT NULL,
  `val_1` int(10) unsigned DEFAULT NULL,
  `val_2` varchar(127) DEFAULT NULL,
  `val_3` varchar(255) DEFAULT NULL,
  `val_4` varchar(127) DEFAULT NULL,
  `val_5` int(10) unsigned DEFAULT NULL,
  KEY `my_wonky_table_id_idx` (`id`),
  KEY `my_wonky_table_timestamp_idx` (`timestamp`),
  KEY `my_wonky_table_val_1_idx` (`val_1`,`id`),
  KEY `my_wonky_table_val_2_idx` (`val_2`,`id`),
  KEY `my_wonky_table_val_4_idx` (`val_4`,`id`),
  KEY `my_wonky_table_val_5_idx` (`val_5`,`id`),
  KEY `my_wonky_table_ip_idx` (`ip`,`id`),
  KEY `my_wonky_table_login_idx` (`login`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (`id`)
(PARTITION pdefault VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
Run Code Online (Sandbox Code Playgroud)

关于查询:它总是SELECT打开id,其他一切都用于过滤.

我想避免的:

  • 关闭数据库实例.
  • 磁盘I/O为100%

我曾想过用这个pt-online-schema-change工具来节流,但是遇到了无主键墙.一个不同的解决方案是在代码中执行此操作,有效地将触发器移动到代码库,并使用有些奇怪的块(例如,使用时间戳列的一小时数据块)慢慢地复制数据,因为没有唯一索引.

是否有其他解决方案和/或工具可用?

Ric*_*mes 6

  1. 创建一个new类似于real表的表,但使用修改后的索引.包括一个,PRIMARY KEY以便您不会再被困.- 这是ALTER,但还不是"人口".
  2. 在新表中,对旧东西使用季度或年度分区; 当前和(稍后)未来分区的每月. - 这是为了减少分区的总数.我的经验法则是"不超过50个分区".(如果您对此计划有疑问,请告诉我.)
  3. 编写脚本以将分区中的所有数据缓慢复制到new表中.我对块的建议在这里可能有用.
  4. 在您赶上之前,创建一个新分区.但是不要复制它.停止上一个分区末尾的"复制"脚本.
  5. 当被捕到除了这个新分区时,停止写入.
  6. 复制最后一个分区. - 这是第4步的成果.
  7. 原子交换: RENAME TABLE real TO old, new TO real;.然后再打开.

强烈建议编写所有脚本并在另一台机器上练习.实践可以是总数的一小部分,但它需要至少有几个分区.