• PostgreSQL记录中的null值是如何存储的


    当向表中插入数据时,可以指定列的值为null。例如,有一张表t(i int,j int,k int),我们可以插入值(8,1,6),或将包含null值的(3,null,7)插入到表中。本文将探讨PostgrSQL中是如何存储null的一些技术细节。

    PostgreSQL如何存储null值的?

    PostgreSQL中的一个元组被分成元组头部分和数据部分。上面提到了向表t插入两条数据的例子。这里,一幅图片被用来抛出这个问题:在元组中null值是如何展示的?

     

    如图中所示,一个int类型的数据占据4个字节的空间,但是遇到null值时,数据库该如何表示在3和7之间有个null值呢?

    PostgreSQL存储null值的方法

    使用pageinspact工具来观察null是如何存储的。执行下面的测试:

    postgres=# create table t(i int, j int, k int);
    CREATE TABLE
    postgres=# insert into t values(8,1,6);
    INSERT 0 1
    postgres=# insert into t values(3,NULL,7);
    INSERT 0 1
    postgres=# insert into t values(4,9,2);
    INSERT 0 1
    postgres=# select lp,t_infomask,t_bits,t_data  from  heap_page_items(get_raw_page('t', 0));
     lp | t_infomask |  t_bits  |           t_data           
    ----+------------+----------+----------------------------
      1 |       2048 |          | x080000000100000006000000
      2 |       2049 | 10100000 | x0300000007000000
      3 |       2048 |          | x040000000900000002000000
    (3 rows)
    
    postgres=#
    

    可以看到,null值没有在元组的数据部分标记出来。

    同时,可以看到带有null值的第二条记录的't_infomask'和’t_bits‘的值与第一条和第三条是不一致的。因此,这可能就是如何读取null值的秘密所在。

    't_bits'设计

    ‘t_bits’是一个uint8的数组,当元组中没有null值的时候,t_bits可以被认为是空的,当元组有null值的列时,t_bits使用一个位(bit)来表示一个列是否为null。

    postgres=# create table t0(i1 int,i2 int,i3 int,i4 int,i5 int,i6 int,
    postgres(# i7 int,i8 int,i9 int,i10 int,i11 int,i12 int
    postgres(# );
    CREATE TABLE
    postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,10,NULL,12);
    INSERT 0 1
    postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,NULL,NULL,12);
    INSERT 0 1
    postgres=# insert into t0 values(1,2,3,4,5,6,7,8,NULL,NULL,NULL,12);
    INSERT 0 1
    postgres=# insert into t0 values(1,2,3,4,5,6,7,8,9,10,11,12);
    INSERT 0 1
    postgres=#
    postgres=# select lp,t_infomask,t_bits  from  heap_page_items(get_raw_page('t0', 0));
     lp | t_infomask |      t_bits      
    ----+------------+------------------
      1 |       2049 | 1111111111010000
      2 |       2049 | 1111111110010000
      3 |       2049 | 1111111100010000
      4 |       2048 | 
    (4 rows)
    
    postgres=#
    

    上面的脚本会创建一个表t0,共有12个列,然后插入几条元组,执行pageinspect工具查询研究元组。注意看元组的t_bits值:

    可以得出结论:

    ·在t_bits中,尚未使用的标记为是0

    ·1表示对应的列是非空的(not null),否则就是null

    表中被删除的列

    在PostgreSQL中,表的列被删除后,这个列的数据结构会被保留在目录中,但是对用户是不可见的。完成下面的测试:

    postgres=# alter table t0 drop column i1;
    ALTER TABLE
    postgres=# insert into t0 values(2,3,4,5,6,7,8,9,10,11,12);
    INSERT 0 1
    postgres=# select lp,t_infomask,t_bits  from  heap_page_items(get_raw_page('t0', 0));
     lp | t_infomask |      t_bits      
    ----+------------+------------------
      1 |       2049 | 1111111111010000
      2 |       2049 | 1111111110010000
      3 |       2049 | 1111111100010000
      4 |       2048 | 
      5 |       2049 | 0111111111110000
    (5 rows)
    
    postgres=#
    

    在这个测试中,我们删除了表t0的列'i1'并插入一个不含有null值的记录。使用pageinspact工具,我们可以发现插入的不含有null值的数据(lp=5)。被删除的列的t_bits值显示其也被认为是null值。

    结论

    当记录没有任何空值时,t_bits不会存储在记录中。一旦存在空值,t_bits将存储在元组中,以记录所有列的空值状态。表的删除列被视为空列。因此,当表中有许多列时,请勿删除列,否则将为每条记录生成额外的t_bit,这将导致存储膨胀。

     

     

     

    https://www.highgo.ca/2020/10/20/the-way-to-store-null-value-in-pg-record/?utm_source=rss&utm_medium=rss&utm_campaign=the-way-to-store-null-value-in-pg-record

  • 相关阅读:
    SQL的四种连接-左外连接、右外连接、内连接、全连接
    查看Linux下端口占用情况的命令
    linux的命令(1)
    xsheell的下载安装初级使用
    日交易,根据权重分配流量的算法,根据权重和交易笔数
    根据权重挑选通道的简单算法
    Java中的String与常量池
    JAVA虚拟机内存分配与回收机制
    JVM 内部运行线程介绍
    AspectJ切入点语法详解
  • 原文地址:https://www.cnblogs.com/abclife/p/13855150.html
Copyright © 2020-2023  润新知