PostgreSQL text类型短数据存储说明

Stella981
• 阅读 488

今天在查看数据库数据文件时,进行一下操作:

CREATE TABLE test ( id int, info text );

INSERT INTO test VALUES (1, ‘abc’), (2, ‘def’);

然后通过hexdump查看数据:

0000000 0000 0000 0140 016f 0000 0000 0020 1fc0
0000010 2000 2004 0000 0000 9fe0 0040 9fc0 0040
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
0001fc0 023f 0000 0000 0000 0000 0000 0000 0000
0001fd0 0002 0002 0802 0018 0002 0000 6409 6665
0001fe0 023f 0000 0000 0000 0000 0000 0000 0000
0001ff0 0001 0002 0802 0018 0001 0000 6109 6362
0002000

发现text类型中的abc和def在数据文件表示为 09616263和09646566,查看代码可知text类型其实为varlena,他的结构为:

struct varlena
{
    char        vl_len_[4];        /* Do not touch this field directly! */
    char        vl_dat[1];
};

前四个字节为长度标识,在这里只有一个字节,而且3个字符的长度为9,百思不得其解啊,遂进行调查,发现,这是因为插入数据较短,数据库给优化了,将原来长度为4个字节的标识为变成了1个:

else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
      VARATT_CAN_MAKE_SHORT(val))
 {
    /* convert to short varlena -- no alignment */
    data_length = VARATT_CONVERTED_SHORT_SIZE(val);
                    
    SET_VARSIZE_SHORT(data, data_length);
    memcpy(data + 1, VARDATA(val), data_length - 1);
}

这里主要是由于SET_VARSIZE_SHORT起的作用:

#define SET_VARSIZE_SHORT(PTR, len)                     SET_VARSIZE_1B(PTR, len)

#ifdef WORDS_BIGENDIAN

#define SET_VARSIZE_1B(PTR,len) \
        (((varattrib_1b *) (PTR))->va_header = (len) | 0x80)

#else

#define SET_VARSIZE_1B(PTR,len) \
        (((varattrib_1b *) (PTR))->va_header = (((uint8) (len)) << 1) | 0x01)

so, 考虑到‘\0’占位情况,即3+1=4,4 << 1 = 8, 8 | 0x01 = 9,于是这里便是9。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Stella981 Stella981
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Easter79 Easter79
2年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
2年前
MongoDB 分片管理(一)检查集群状态
一、检查集群状态1.1使用sh.status()查看集群摘要信息1、使用sh.status()可以查看分片信息、数据库信息、集合信息sh.status()如果数据块较多时,使用sh.status(true)又是输出会很多,就不会截断,要使用如下查看2、tooman
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这