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)


      目录
      相关文章
      |
      6月前
      |
      关系型数据库 MySQL 数据库
      Flink CDC中mysql 字段设置了默认值 ,然后插入数据时 指定该字段为null 会返回字段默认值 而不是null?
      Flink CDC中mysql 字段设置了默认值 ,然后插入数据时 指定该字段为null 会返回字段默认值 而不是null?
      154 2
      |
      11月前
      |
      人工智能
      ES中更新字段和删除字段的操作
      ES中更新字段和删除字段的操作
      |
      11月前
      |
      SQL 关系型数据库 MySQL
      列的完整性约束——设置表字段的默认值(DEFAULT)
      列的完整性约束——设置表字段的默认值(DEFAULT)
      |
      11月前
      |
      SQL 关系型数据库 MySQL
      史上最简单的 MySQL 教程(九)「列属性 之 空属性、列描述和默认值」
      史上最简单的 MySQL 教程(九)「列属性 之 空属性、列描述和默认值」
      59 0
      具有默认值的表
      具有默认值的表
      51 1
      |
      SQL 关系型数据库 MySQL
      MySQL 数据库利用alter语句修改表字段属性实例演示,如何拓展表字段长度,sql语句修改表字段名称和类型
      MySQL 数据库利用alter语句修改表字段属性实例演示,如何拓展表字段长度,sql语句修改表字段名称和类型
      339 0
      MySQL 数据库利用alter语句修改表字段属性实例演示,如何拓展表字段长度,sql语句修改表字段名称和类型
      |
      机器学习/深度学习 SQL 关系型数据库
      PostgreSQL 11 新特性解读 : 新增非空默认值字段不需要重写表
      PostgreSQL 10 版本前表新增不带默认值的DDL不需要重写表,只需要更新数据字典,因此DDL能瞬间执行,如下: ALTER TABLE table_name ADD COLUMN flag text; 如果新增的字段带默认值,则需要重写表,表越大,执行时间越长,如下。
      5219 0
      EF部分字段更新,自动忽略null字段
      原文:EF部分字段更新,自动忽略null字段  某个项目里的update代码是类似这样的 public T Update(T entity) where T : ModelBase { var set = this.
      1558 0