我有一个MySQL表,有120M行,大小约120GB:

CREATE TABLE `impressions` (
  `session_uuid` varchar(36) DEFAULT NULL,
  `survey_uuid` varchar(255) NOT NULL,
  `data` text,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `user_uuid` varchar(255) NOT NULL DEFAULT '',
  `is_test` tinyint(1) NOT NULL DEFAULT '0',
  KEY `impressions_survey_uuid_session_uuid_user_uuid_index` (`survey_uuid`,`session_uuid`,`user_uuid`),
  KEY `impressions_created_at_index` (`created_at`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

我发现这个数据迁移需要6个多小时(在一个不错的RDS实例上,我可以运行更复杂的迁移),因为它需要进行大量的I/O操作.为什么要做这么多的手术?这里我唯一要更改的是空可选性和默认值.

ALTER TABLE `impressions` CHANGE COLUMN `user_uuid` `user_uuid` VARCHAR(255) null;

推荐答案

更改列的可空性会更改InnoDB中的行 struct .InnoDB中存储的一行对于每个可为NULL的列都有一个位图,以指示该列在给定行上是否实际上为NULL.如果更改列的可空性,则更改了位图的长度.因此,每一行都必须重写为一组新的页面.

仅更改默认值是仅更改元数据.

我犯了一个错误,运行了一个本应是仅元数据更改的ALTER表,但我忘记了匹配原始列的可空性,因此我的ALTER表变成了一个表重组,花费了很长时间.

如果您必须在MySQL中进行这样的更改,我建议您使用一种开源的在线模式更改工具:pt-online-schema-changegh-ost.我使用前一个工具来管理生产中许多长期运行的模式更改.这通常会使操作花费更长的时间,但这不是问题,因为在模式更改过程中,表仍然可以用于读写.

Mysql相关问答推荐

慢查询日志(log)甚至包括快速查询,因为它包括等待锁定所花费的时间

如何防止程序中计数器出错

运行简单查询时Prisma预准备语句错误

仅获取我不是最后一个 comments 者的博客帖子

在两个日期之间生成每个月的1行数据.

使用 SELECT 时应锁定多少行 .. FOR UPDATE LIMIT 1

如何在 MySQL 中使用从 SELECT IF 返回的布尔值

最后一个字母 '%n' 的 mysql SELECT 字符串不起作用

Mysql,显示谁已经和没有 Select 退出巴士服务

Mysql insert with loop out of select 语句

为什么 ORDER BY 'id' 'desc' 不返回语法错误?

主键应该始终是无符号的?

终止空闲的mysql连接

当您无法修复表时,如何修复 MySQL不正确的密钥文件错误?

MYSQL:创建表中的索引关键字以及何时使用它

按日期和时间降序排序?

如何用一系列日期填充表格?

MySQL - 我如何输入 NULL?

如何使用 XML_LOAD() 将 XML 文件导入 MySQL 数据库表;功能

当运行 UPDATE ... datetime = NOW();所有更新的行都会有相同的日期/时间吗?