暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据库运维 -- KingbaseES 如何做到增加非空列而无需重写表

原创 金仓数据库 2024-07-26
332

熟悉Oracle的DBA就知道,Oracle早期11g版本在增加非空列(default or not null default)时,需要回写表,也就是需要针对每一行的记录进行修改。Oracle12c 开始,修改或增加非空字段都无需更新数据表。对于KingbaseES ,增加非空列同样不需要更新数据,alter table操作可以快速返回,将对业务的影响降低到最小。KingbaseES是如何做到的?我们来看实际例子。

一、测试过程

test=# create table tab01(id integer,name varchar(100));
CREATE TABLE
test=# insert into tab01 select generate_series(1,10000000),md5(random());
INSERT 0 10000000
test=# create index idx_tab01_id on tab01(id);
CREATE INDEX
test=# select sys_relation_filepath('tab01');
 sys_relation_filepath
-----------------------
 base/13529/16408

#千万级数据,alter操作瞬间完成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
#即使列上有索引,alter table操作也瞬间完成 test=# alter table tab01 alter column name type varchar(200); ALTER TABLE test=# select sys_relation_filepath('tab01'); sys_relation_filepath ----------------------- base/13529/16408

可以看到,alter table 的过程瞬间完成(间接推断出不会去修改底层数据),表的底层存储文件也没变动。那KingbaseES是如何做到这点的?

二、机制分析

KingbaseES 之所以能做到无需修改底层数据,是由于系统表 sys_attribute 有两个字段:atthasmissing 和 attmissingval。我们来看具体的值:

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 。

test=# vacuum full tab01;
VACUUM
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函数的特性,需要在增加列时就执行,也就是必须立即修改行数据。来看实际例子:

test=# drop table tab01;
DROP TABLE
test=# create table tab01(id integer,name varchar(100));
CREATE TABLE
test=# insert into tab01 select generate_series(1,1000000),null;
INSERT 0 1000000
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 时就得修改每行数据。
最后修改时间:2024-12-19 19:18:27
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论