ALTER TABLE多操作的表遍历与MySQL DROP COLUMN执行机制问询
针对你提出的关于MySQL InnoDB下ALTER TABLE多列操作的两个问题,我来详细解答一下:
问题1:多列操作的ALTER TABLE语句是否只会遍历所有行一次并完成所有所需变更?
在你设定的前提条件下(使用InnoDB引擎,待修改/删除的列无索引、无复杂默认值,也就是单独执行时无需临时表的变更),组合式的ALTER TABLE语句确实只会遍历表的所有行一次,完成所有指定的变更。
举个例子,像这样的组合操作:
ALTER TABLE `my_table` DROP COLUMN `column_1`, MODIFY `column_2` INT NOT NULL;
对比分开执行两条ALTER TABLE语句,MySQL会把这些可合并的in-place变更打包处理,只做一次全表扫描,就能完成列的删除标记和列属性修改。而如果分开执行,每一条ALTER TABLE都需要单独扫描一次表,性能开销会大很多。
这种合并操作是MySQL对非标准SQL的扩展,目的就是减少全表扫描的次数,提升大表变更的效率。
问题2:MySQL(InnoDB引擎)实际如何执行DROP COLUMN操作?是先隐藏列还是直接删除数据?
InnoDB执行DROP COLUMN时,并不会立即物理删除磁盘上的列数据,而是采用“隐藏标记”的方式:
DROP COLUMN形式不会物理删除列,仅使其对SQL操作不可见……
也就是说,执行DROP COLUMN后,该列的数据仍然存在于磁盘的表空间中,但MySQL会在表的元数据里把这个列标记为不可访问,后续的SELECT、INSERT等SQL操作都看不到这个列。
只有当后续执行了需要重建表的操作(比如ALTER TABLE ... FORCE,或者添加索引、修改列类型这类需要重建表的变更)时,InnoDB才会在重建表的过程中真正移除这些被标记为删除的列的数据,释放对应的磁盘空间。
这种设计的好处是让DROP COLUMN操作变得非常高效,不需要立即扫描和修改所有行的数据,尤其适合大表的快速变更。
内容的提问来源于stack exchange,提问作者Geekfish

