KingbaseES 如何做到增加非空列而无需重写表
熟悉Oracle的DBA就知道,Oracle早期11g版本在增加非空列(default or not null default)时,需要回写表,也就是需要针对每一行的记录进行修改。Oracle12c 开始,修改或增加非空字段都无需更新数据表。对于KingbaseES ,增加非空列同样不需要更新数据,alter table操作可以快速返回,将对业务的影响降低到最小。KingbaseES是如何做到的?我们来看实际例子。
一、测试过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | test=# create table tab01(id integer , name varchar (100)); CREATE TABLE 时间:2.498 ms test=# insert into tab01 select generate_series(1,10000000),md5(random()); INSERT 0 10000000 时间:49114.272 ms (00:49.114) test=# create index idx_tab01_id on tab01(id); CREATE INDEX 时间:12344.101 ms (00:12.344) test=# select sys_relation_filepath( 'tab01' ); sys_relation_filepath ----------------------- base/13529/16408 --千万级数据,alter操作瞬间完成<br>test=# ALTER TABLE tab01 add city varchar2(50) default 'FuZhou' not null; ALTER TABLE 时间:2.427 ms test=# select sys_relation_filepath( 'tab01' ); sys_relation_filepath ----------------------- base/13529/16408 test=# create index idx_tab01_name on tab01( name ); CREATE INDEX 时间:132274.806 ms (02:12.275)<br><br> --即使列上有索引,alter table操作也瞬间完成 test=# alter table tab01 alter column name type varchar (200); ALTER TABLE 时间:3.506 ms test=# select sys_relation_filepath( 'tab01' ); sys_relation_filepath ----------------------- base/13529/16408 |
可以看到,修改的过程瞬间完成(间接推断出不会去修改底层数据),表的底层存储文件也没变动。那KingbaseES是如何做到这点的?
二、机制分析
KingbaseES 之所以能做到无需修改底层数据,是由于系统表 sys_attribute 有两个字段:atthasmissing 和 attmissingval。我们来看具体的值:
1 2 3 4 5 6 | test=# select attname, attmissingval, atthasmissing from pg_attribute where attnum > 0 and attrelid = 'tab01' ::regclass; attname | attmissingval | atthasmissing ---------+---------------+--------------- id | | f name | | f city | {FuZhou} | t |
可以看到新增加的非空列 atthasmissing=true,也就是告诉查询执行器,该非空列在数据行有部分没数据,而如果没有数据,就用attmissingval值替代。
如果表重整,则数据会写回行,不再需要 atthasmissing 和 attmissingval 。
1 2 3 4 5 6 7 8 9 10 | test=# vacuum full tab01; VACUUM 时间:148090.441 ms (02:28.090) test=# select attname, attmissingval, atthasmissing from pg_attribute where attnum > 0 and attrelid = 'tab01' ::regclass; attname | attmissingval | atthasmissing ---------+---------------+--------------- id | | f name | | f city | | f (3 行记录) |
可以看到,vacuum full 后,atthasmissing 和 attmissingval 数据已经没有了,因为数据已写回每行。
三、需要重写表的场景
增加的列默认值通过volatile类型函数生成。由于volatile函数的特性,需要在增加列时就执行,也就是必须立即修改行数据。来看实际例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | test=# drop table tab01; DROP TABLE 时间:135.531 ms test=# create table tab01(id integer , name varchar (100)); CREATE TABLE 时间:2.412 ms test=# insert into tab01 select generate_series(1,1000000), null ; INSERT 0 1000000 时间:1174.976 ms (00:01.175) test=# ALTER TABLE tab01 add city varchar2(50) default random() not null ; ALTER TABLE 时间:1106.471 ms (00:01.106) test=# select attname, attmissingval, atthasmissing from pg_attribute where attnum > 0 and attrelid = 'tab01' ::regclass; attname | attmissingval | atthasmissing ---------+---------------+--------------- id | | f name | | f city | | f (3 行记录) |
可以看到,如果default 值是通过 random (volatile 类型函数)函数生成,则在alter table 时就得修改每行数据。
KINGBASE研究院
分类:
SQL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!