zoukankan      html  css  js  c++  java
  • postgresql磁盘存储结构

    1.  Page header24Byte

    1.1.  描述

    记录页头的信息。

    1.2.  get_raw_page函数

    将指定表文件中的页面内容返回,param1:表名,param2main/fsm/vm, param3:第几页

    1.3.  page_header(函数)

    作用:

    返回本页面中的page header信息。param1get_raw_page函数的返回值。

    page的前24字节存储head data

    字段:

           lsn:记录最后一次对页修改的xlog记录

           checksum:页面的校验和,用于判断当前页是否完整

           flags:(指示当前页的状态)

           lower:本页空闲位置的起始指针

           uper:本业空闲位置的结束指针

           special:页预留的位置

           pagesize:页面大小

           version:当前版本

           prune_xid:最后一次删除或更新的xid

           页后面存储的是元组(tuple)信息的数据(表的数据行,一个元组信息就是一行),也就是下一节的page item

    1.4.  图解

    2.  Page item(页内存储的tuple数据)

    一条数据(数据库行)由Item ID + Tuple Header + data(实际数据,由用户写入)组成。

    Item IdPage head存放在一起,存在页的一端,Tuple Header + data 存放在一起,存放在页的另一端。

    1.5.  Item ID(行指针,4字节)

           

    1.6.  Tuple Header(元组头,23字节)

    描述元组数据的数据,描述本条数据(数据库行)的状态,事物id等。

    由于数据存储需要对齐(8的整数倍,整体对外长度为24字节),空行的长度为24字节。另外还有4字节的指针。即一条空行总共占用24+4=28字节。

           

    1.7.  heap_page_items函数

    显示堆页面上的所有行指针。param1get_raw_page函数的返回值

           lp:

           lp_off: tuple在页面中的位置

           lp_len:tuple的实际长度(tuple header + data,最终长度需要取整为8B的整数倍)

           t_xmint_xmax: 插入,删除和更新时的事物id,插入时xmin写入当前事物id,删除时xmax写入事物id。更新也是先删除再插入

           t_field3:

           t_ctid:物理id,用于寻址数据在该页的位置(或者用于指向下一页索引)

    1.8.  实战1-单条数据占用内存

    l  sql语句

           drop table if EXISTS test1;

    create table test1(id int);

    --vacuum analyze test1;

    insert into test1 values(1);

    select * from page_header(get_raw_page('test1', 'main', 0));

    insert into test1 values(2);

    select * from page_header(get_raw_page('test1', 'main', 0));

    insert into test1 values(300);

    select * from page_header(get_raw_page('test1', 'main', 0));

    select * from heap_page_items(get_raw_page('test1',0));

    l  分析

           通过下图可以看出,每插入一条int数据,lower增加4字节(item id是从页头开始写的,写在header的后面),upper减少32字节(tuple是从页尾开始写的,tuple header + data = 24 + 4 = 28,因为要取8的整数倍,所以为32字节)。

    t_data存放的是数据的内容,注意下面标红的2c010000(实际是0X012c)对应值为300.

    l  额外结论

    根据上面的理论,目前来看,存储4字节的int8字节的int消耗磁盘大小是一样的。(该定论局限于本表只有一个字段的情况下)

    可以通过以下方式证明:

                  drop table if EXISTS test1;

    create table test1(id char(7));

    insert into test1 values('a');

    select * from page_header(get_raw_page('test1', 'main', 0));

    insert into test1 values('b');

    select * from page_header(get_raw_page('test1', 'main', 0));

    insert into test1 values('c');

    select * from page_header(get_raw_page('test1', 'main', 0));

    select * from heap_page_items(get_raw_page('test1',0));

    说明:char的长度可以手动指定,char中的长度7实际占用8字节。

    另外:

      null字段不占用tuple中的空间

      定长字段(int,char...)占用磁盘空间固定,和声明的一致

      变长字段(varchar, text...)占用的磁盘空间由实际数据而定,而不是声明的长度。

    1.9.  实战2-计算单页的存储量(226行)

    计算一页可以存储的单列int类型数据数量

    l  已知

           page页默认大小为8KB8192字节)

    page header 24字节

           每插入一行,生成一个item id4字节)和一个tupletuple header + data,共32字节)。

    l  理论值

           (8192-24/ 36 = 226

    (8192-24% 36 = 32

    所以理论上,一页可以存储226行只有一个int列的数据,属于空间大小为32B

    l  测试sql

           drop table if EXISTS test1;

    create table test1(id int);

    insert into test1 select generate_series(1,226);

    select * from page_header(get_raw_page('test1', 'main', 0));

    select * from heap_page_items(get_raw_page('test1',0));

    select count(*) from heap_page_items(get_raw_page('test1',0));

    insert into test1 values(300);

    l  分析

           插入226条数据后,通过page heaader查看upper-lower=32

           通过page items查看第一页存在226条数据。

           再插入一条,发现第一页还是226条数据,第二页有一条数据

           说明第一页已经插满。

     

    3.  存储结构

    l  存储方式共有4

    PLAIN :避免压缩和行外存储。

    EXTENDED :先压缩,后行外存储。

    EXTERNAL :允许行外存储,但不许压缩。

    MAIN :允许压缩,尽量不使用行外存储更贴切。

    l  何时压缩Tuple数据

           Tuple大小超过大概2KB时,PostgreSQL会尝试基于LZ压缩算法进行压缩。

    l  何时行外存储(TOAST

    行外存储toasted属性的本意是The Oversized-Attribute Storage Technique,对于某个超长的属性单独存储。当某行数据超过PostgreSQL页大小(8k)后,会将这个页放到系统命名空间pg_toast下的一个单独的表中,而在原表中存储一个TOAST pointer

    l  实战解读

    create table tab3(id int primary key,info text);

     备注:

      https://www.postgresql.org/docs/current/storage-page-layout.html     官方文档

  • 相关阅读:
    显示文件本地文件夹
    Select Dependencies选择依赖项
    搜索小技巧
    783. Minimum Distance Between BST Nodes BST节点之间的最小距离
    5. Longest Palindromic Substring 最长的回文子串
    12. Integer to Roman 整数转罗马数字
    3. Longest Substring Without Repeating Characters 最长的子串不重复字符
    539. Minimum Time Difference 最小时差
    43. Multiply Strings 字符串相乘
    445. Add Two Numbers II 两个数字相加2
  • 原文地址:https://www.cnblogs.com/gc65/p/11011885.html
Copyright © 2011-2022 走看看