为什么我的MariaDb不使用INSTANT算法向大型表中添加列

roejwanj  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(153)

我在MariaDb(10.4.10-MariaDB-1:10.4.10+maria~bionic)中有一个巨大的表,我正在使用

alter table Appointment add column responsible_organization varchar(256);

现有表如下:

CREATE TABLE `Appointment` (
    `id` VARCHAR(256) NOT NULL,
    `version` VARCHAR(24) NOT NULL,
    `repetition_ref` VARCHAR(256) NULL DEFAULT NULL,
    `type` VARCHAR(256) NULL DEFAULT NULL,
    `comment` VARCHAR(2048) NULL DEFAULT NULL,
    `description` VARCHAR(2048) NULL DEFAULT NULL,
    `end` DATETIME NULL DEFAULT NULL,
    `start` DATETIME NULL DEFAULT NULL,
    `status` VARCHAR(256) NULL DEFAULT NULL,
    `statuschangedate` DATETIME NULL DEFAULT NULL,
    `deliverystatus` VARCHAR(256) NULL DEFAULT NULL,
    `reasoncancelled` VARCHAR(256) NULL DEFAULT NULL,
    `visit_type` VARCHAR(256) NULL DEFAULT NULL,
    `modified_db_time` TIMESTAMP(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3),
    `markedasdeleted` DATETIME NULL DEFAULT NULL,
    PRIMARY KEY (`id`, `version`),
    INDEX `FKc4f6e4y3ftaya162pwf7v4uj4` (`deliverystatus`),
    INDEX `FKeuhxsh83rlweegn404penommb` (`reasoncancelled`),
    INDEX `FK5xmurewn61wf4n3of5yx2nsmg` (`visit_type`),
    INDEX `modified_db_time` (`modified_db_time`),
    CONSTRAINT `FK5xmurewn61wf4n3of5yx2nsmg` FOREIGN KEY (`visittype`) REFERENCES `Coding` (`id`),
    CONSTRAINT `FKc4f6e4y3ftaya162pwf7v4uj4` FOREIGN KEY (`deliverystatus`) REFERENCES `CodeableConcept` (`id`),
    CONSTRAINT `FKeuhxsh83rlweegn404penommb` FOREIGN KEY (`reasoncancelled`) REFERENCES `CodingDt` (`id`)
)
;

就我所读的MariaDb文档而言,如果我不指定任何算法,它应该选择最有效的算法。我希望它至少使用INPLACE。但是当我运行它时,我可以在进程列表中看到它正在运行,状态为“复制到临时表”。所以这是COPY算法,对吗?
然后,我试图强制它使用@o-jones建议的INSTANT,得到的输出如下:

MariaDB [mydb]> alter table Appointment add column responsibleorganisation varchar(256), ALGORITHM=INSTANT;
ERROR 1846 (0A000): ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY

奇怪,因为我添加了一列。
我想知道这是否与在旧版本的MariaDb上创建的表有关,并且最近没有重建。我发现references to this being an issue适用于具有旧样式时态列的表。
变量old_alter_tablealter_algorithm的值均为DEFAULT
我的表有1.1亿多行,所以我想找到一种方法来优化它。
有什么想法吗?

r8uurelv

r8uurelv1#

MariaDB Server 10.4.10发布于2年前,即2019年11月。更新的版本是否可重复?自那时以来,ALTER TABLE已进行了一些修复。
如果这个问题在10.4系列的最新版本中是可重复的,我建议您在https://jira.mariadb.org中提交一个bug报告,并使用最少的可重复测试用例(CREATE TABLEALTER TABLE语句)。
在更新的版本中,答案可能是MDEV-20590引入了一种方法来禁用涉及更改数据文件格式的即时操作。SET GLOBAL innodb_instant_alter_column_allowed=never;将使ADD COLUMN始终重建表,就像在MariaDB Server 10.3之前所做的那样。

mwecs4sa

mwecs4sa2#

我在MariaDB的早期版本中创建数据库时遇到过这种情况。有时候某些列的存储格式发生了变化,但升级并没有重写所有数据。而是等待某些模式发生变化,然后修改底层数据格式。在我的案例中,这是因为某些列是date/datetime,并且在10.3中临时存储格式发生了变化。但我的许多表仍然是旧格式,我在10.4中所做的任何模式更改都希望更新所有这些列的格式,这对于具有数百万行的表来说是一件痛苦的事情。
如果您先使用“ALTER TABLE tab_name ENGINE = InnoDB;则列add将能够“立即”添加。尽管改变将花费与非即时列add一样长的时间。然而,存在分开地进行这些过程可能是有利的情况。
在我的例子中,我不得不执行手动表重建,因为我不允许活动表在重建所需的时间内被锁定,所以我编写了一个存储过程来获取表并逐渐创建它的副本,并使副本保持最新。拷贝过程被限制,以避免对数据库造成太大压力,一旦拷贝准备就绪,我就可以交换旧表和新表快速重命名,以便停机时间以秒而不是小时为单位测量。一旦新表到位,我就可以像平常一样对它进行即时DDL操作了。

相关问题