PG11新特性解读:新增非空默认值字段不需要重写表

简介: PG11新特性解读:新增非空默认值字段不需要重写表

PG11新特性解读:新增非空默认值字段不需要重写表


1、如何理解这个特性


postgresql11之前,为表增加一个包含非空默认值的字段,将会导致表重写,为每一行添加该字段,并填充默认值。如果该表在增加字段前非常大,那么将会非常耗时。

而在11版本中,新增加一个功能,将不再重写表。而是将非空默认值的属性添加到系统表pg_attribute中,该表描述每一列的信息。

1)系统表pg_attribute存储所有列信息


postgres=# \d pg_attribute
              Table "pg_catalog.pg_attribute"
    Column     |   Type    | Collation | Nullable | Default
---------------+-----------+-----------+----------+---------
 attrelid      | oid       |           | not null |
 attname       | name      |           | not null |
 atttypid      | oid       |           | not null |
 attstattarget | integer   |           | not null |
 attlen        | smallint  |           | not null |
 attnum        | smallint  |           | not null |
 attndims      | integer   |           | not null |
 attcacheoff   | integer   |           | not null |
 atttypmod     | integer   |           | not null |
 attbyval      | boolean   |           | not null |
 attstorage    | "char"    |           | not null |
 attalign      | "char"    |           | not null |
 attnotnull    | boolean   |           | not null |
 atthasdef     | boolean   |           | not null |
 atthasmissing | boolean   |           | not null |
 attidentity   | "char"    |           | not null |
 attgenerated  | "char"    |           | not null |
 attisdropped  | boolean   |           | not null |
 attislocal    | boolean   |           | not null |
 attinhcount   | integer   |           | not null |
 attcollation  | oid       |           | not null |
 attacl        | aclitem[] |           |          |
 attoptions    | text[]    | C         |          |
 attfdwoptions | text[]    | C         |          |
 attmissingval | anyarray  |           |          | 
Indexes:
    "pg_attribute_relid_attnam_index" UNIQUE, btree (attrelid, attname)
    "pg_attribute_relid_attnum_index" UNIQUE, btree (attrelid, attnum)

 

在表pg_attribute增加了2个字段,atthasmings和attmissingval。如果新增字段有非空默认值,那么atthasmings置为true,attmissingval为默认值。

例如:


postgres=# alter table t1 add column id3 int default 5;
ALTER TABLE
postgres=# select atthasmissing,attmissingval from pg_attribute where attrelid=16387 and attname='id3';
 atthasmissing | attmissingval
---------------+---------------
 t             | {5}
(1 row)

 

2)系统表pg_attrdef,存储所有列的默认值,这个表不管是否是alter table添加非空默认值字段

    postgres=# \d pg_attrdef
                  Table "pg_catalog.pg_attrdef"
     Column  |     Type     | Collation | Nullable | Default
    ---------+--------------+-----------+----------+---------
     oid     | oid          |           | not null |
     adrelid | oid          |           | not null |
     adnum   | smallint     |           | not null |
     adbin   | pg_node_tree | C         | not null |
    Indexes:
        "pg_attrdef_adrelid_adnum_index" UNIQUE, btree (adrelid, adnum)
        "pg_attrdef_oid_index" UNIQUE, btree (oid

     


    postgres=# select *from pg_attrdef ;
      oid  | adrelid | adnum |                                                                    adbin                                                                    
    -------+---------+-------+---------------------------------------------------------------------------------------------------------------------------------------------
     16390 |   16387 |     3 | {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location 42 :constvalue 4 [ 5 0 0 0 ]}
    (1 row)

     

    pg_node_tree是什么数据类型?

     

    3)对于表中已存在的行查询时返回attmissingval属性的值,插入新的行,若指定带默认值字段,则查询时不需要返回attmissingval属性的值,否则需要返回attmissingval属性的值:


    postgres=# select *from t1;
     id1 | id2 | id3
    -----+-----+-----
       1 |   2 |   
    (1 row)

     


    postgres=# insert into t1 values(2,3,NULL);
    INSERT 0 1
    postgres=# select *from t1;
     id1 | id2 | id3
    -----+-----+-----
       1 |   2 |   5
       2 |   3 |    
    (2 rows)
    postgres=# insert into t1 (id1,id2) values(3,4);
    INSERT 0 1
    postgres=# select *from t1;
     id1 | id2 | id3
    -----+-----+-----
       1 |   2 |   5
       2 |   3 |    
       3 |   4 |   5
    (3 rows)

     

    4)一旦该表被重写(vacuum full table操作),那么pg_attribute新增的两个字段值将被清除:


    postgres=# select atthasmissing,attmissingval from pg_attribute where attrelid=16387 and attname='id3';
     atthasmissing | attmissingval
    ---------------+---------------
     f             |
    (1 row)

     

    但是 pg_attrdef的值不会清除

      postgres=# select *from pg_attrdef ;
        oid  | adrelid | adnum |                                                                    adbin                                                                    
      -------+---------+-------+---------------------------------------------------------------------------------------------------------------------------------------------
       16390 |   16387 |     3 | {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location 42 :constvalue 4 [ 5 0 0 0 ]}
      (1 row)


      目录
      相关文章
      |
      2月前
      |
      SQL 关系型数据库 MySQL
      MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
      MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
      175 0
      |
      4月前
      |
      SQL 存储 索引
      MySQL设计规约问题之为什么应该把字段定义为NOT NULL并且提供默认值
      MySQL设计规约问题之为什么应该把字段定义为NOT NULL并且提供默认值
      |
      关系型数据库 MySQL 数据库
      Flink CDC中mysql 字段设置了默认值 ,然后插入数据时 指定该字段为null 会返回字段默认值 而不是null?
      Flink CDC中mysql 字段设置了默认值 ,然后插入数据时 指定该字段为null 会返回字段默认值 而不是null?
      236 2
      |
      存储 SQL 关系型数据库
      mysql新增表或字段时判断是否存在
      mysql新增表或字段时判断是否存在
      1018 0
      |
      关系型数据库 MySQL 数据库
      mysql创建表后修改表中id属性默认为空
      mysql创建表后修改表中id属性默认为空
      具有默认值的表
      具有默认值的表
      71 1
      |
      关系型数据库 MySQL 索引
      Mysql 唯一索引的字段值 允许多个NULL值存在吗
      Mysql 唯一索引的字段值 允许多个NULL值存在吗
      659 0
      Mysql 唯一索引的字段值 允许多个NULL值存在吗
      |
      机器学习/深度学习 SQL 关系型数据库
      PostgreSQL 11 新特性解读 : 新增非空默认值字段不需要重写表
      PostgreSQL 10 版本前表新增不带默认值的DDL不需要重写表,只需要更新数据字典,因此DDL能瞬间执行,如下: ALTER TABLE table_name ADD COLUMN flag text; 如果新增的字段带默认值,则需要重写表,表越大,执行时间越长,如下。
      5407 0
      |
      新零售 关系型数据库 数据库
      PostgreSQL技术周刊第9期:PostgreSQL 11新特性解读之新增非空默认值字段不需要重写表
      PostgreSQL(简称PG)的开发者们:云栖社区已有5000位PG开发者,发布了3000+PG文章(文章列表),沉淀了700+的PG精品问答(问答列表)。 PostgreSQL技术周刊会为大家介绍最新的PG技术与动态、预告活动、最热问答、直播教程等,欢迎大家订阅PostgreSQL技术周刊。
      3887 0