PostgreSQL中的数据对齐

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 当数据自然对齐时,CPU可以有效地对内存执行读写操作。因此,PostgreSQL中的每种数据类型都有特定的对齐要求。本文会对PG中的对齐进行简单的介绍


PG中的数据对齐(译)

翻译自:https://www.enterprisedb.com/postgres-tutorials/data-alignment-postgresql

当数据自然对齐时,CPU可以有效地对内存执行读写操作。因此,PostgreSQL中的每种数据类型都有特定的对齐要求。当在一个元组中连续存储多个属性时,在属性之前插入填充,使其从所需的对齐边界开始。更好地理解这些对齐要求可能有助于减少在磁盘上存储元组时所需的填充量,从而节省磁盘空间。

Postgres中的数据类型分为以下几类:

  1. Pass-by-value, fixed length:通过值传递给Postgres内部例程并具有固定长度的数据类型属于这种类型。长度可以是1、2或4个字节(64位系统上为8个字节)。
  2. Pass-by-reference, fixed length:  对于这些数据类型,内存堆页中的地址引用被发送到内部Postgres例程。它们也有固定的长度。
  3. Pass-by_reference, variable length:   对于可变长度的数据类型,Postgres在实际数据之前添加一个varlena头。它存储了一些关于数据如何实际存储在磁盘上的信息(未压缩、压缩或TOASTed)以及数据的实际长度。对于 TOAST 属性,实际数据存储在一个单独的关系中。在这些情况下,varlena标头后面跟着一些关于数据在相应TOAST关系中的实际位置的信息。

通常,varlena头的磁盘上大小是1字节。但是,如果不能  TOAST 数据,并且未压缩数据的大小超过126个字节,则使用4个字节的头。例如,

CREATETABLE t1 (

, a varchar

);

insertinto t1 values(repeat('a',126));

insertinto t1 values(repeat('a',127));

select pg_column_size(a)from t1;

pg_column_size

---------------------

         127

         131

此外,具有4字节varlena头的属性需要与4字节对齐的内存位置对齐。它可能会浪费多达3字节的额外填充空间。因此,对这些列进行一些谨慎的长度限制可能会节省空间。

  1. Pass-by_reference,可变长度(cstring, unknown):最后,有两种数据类型,即ctring和unknown,它们都是字符串字面量。它们可以从任何1字节对齐的边界存储。而且,它们不需要任何varlena头文件。

可以使用以下查询检查每种类型的对齐要求,

selecttypname,typbyval,typlen,typalignfrompg_type;

 

// 输出

---------------------------------------------------------------------

               typname                |typbyval|typlen|typalign

---------------------------------------+----------+--------+----------

bool                                  |t        |      1|c

bytea                                 |f        |     -1|i

char                                  |t        |      1|c

name                                  |f        |     64|c

int8                                  |t        |      8|d

int2                                  |t        |      2|s

int2vector                            |f        |     -1|i

int4                                  |t        |      4|i

其中typname是数据类型的名称;

typbyval如果数据类型是通过值传递访问的,则为true,否则为false;

typlen是数据类型的实际长度,但是对于可变长度的数据类型,它的值< 0 (cstring和unknown为-2,否则为-1);

typalign是数据类型所需的对齐方式。其含义如下所示:

/home/gtwang/postgresql-13.2/src/include/catalog/pg_type.h

     

     *'c'=CHARalignment, ienoalignmentneeded.

     *'s'=SHORTalignment (2bytesonmostmachines).

     *'i'=INTalignment (4bytesonmostmachines).

     *'d'=DOUBLEalignment (8bytesonmanymachines, butbynomeansall).

     * (UsetheTYPALIGNmacrosbelowforthese.)

在检查了每种数据类型的对齐要求之后,您可以通过以有利于对齐的方式定位它们来减少填充空间。例如,下面的表模式浪费了大量的磁盘空间来填充:

CREATETABLE t1 (

, a char

, b int2    -- 1 byte of padding after a

, c char

, d int4    -- 3 bytes of padding after c

, e char

, f int8    -- 7 bytes of padding after e

);

如果将列重新按照对齐要求排序:首先double 齐列,然后int对齐,最后短对齐和char对齐列,则可以为每个元组节省(1+3+7)=11字节的空间。

CREATETABLE t1 (

, f int8

, d int4

, b int2

, a char

, c char

, e char

);

在元组属性之前,存储一个固定大小的23字节的元组头,后跟一个可选的空位图和一个可选的对象ID。属性总是从maxaligned边界开始—在64位操作系统上通常为8字节(或在32位操作系统上为4字节)。因此,最小元组报头的有效大小是24字节(23字节报头+ 1字节填充)。当存在空位图时,它会占用足够的字节,使每个数据列都有一个位。在这个位列表中,1位表示非空,0位表示空。当位图不存在时,所有列都假定为非空。例如[3],

SELECT pg_column_size(row(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));

pg_column_size

----------------

           24

上面这里例子包含了23个字节的固定大小的元组头和一个由8位组成的空位图。现在,如果我们将列数增加到9,它将包括23个字节的固定大小的元组头,一个由16位和7字节填充组成的空位图。

在由数百万行组成的关系中,为每个元组节省几个字节可能会节省一些重要的存储空间。此外,如果我们可以在一个数据页中放入更多的元组,性能就可以由于较少的I/O活动而得到提高。


相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
7月前
|
SQL Oracle 关系型数据库
实时计算 Flink版操作报错之往GREENPLUM 6 写数据,用postgresql-42.2.9.jar 报 ON CONFLICT (uuid) DO UPDATE SET 语法有问题。怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
7月前
|
关系型数据库 PostgreSQL
PostgreSQL排序字段不唯一导致分页查询结果出现重复数据
PostgreSQL排序字段不唯一导致分页查询结果出现重复数据
162 0
|
关系型数据库 MySQL Linux
TiDB实时同步数据到PostgreSQL(三) ---- 使用pgloader迁移数据
使用PostgreSQL数据迁移神器pgloader从TiDB迁移数据到PostgreSQL,同时说明如何在最新的Rocky Linux 9(CentOS 9 stream也适用)上通过源码编译安装pgloader。
|
27天前
|
存储 关系型数据库 数据库
【赵渝强老师】PostgreSQL的数据文件
PostgreSQL的物理存储结构主要包括数据文件、日志文件等。数据文件按oid命名,超过1G时自动拆分。通过查询数据库和表的oid,可定位到具体的数据文件。例如,查询数据库oid后,再查询特定表的oid及relfilenode,即可找到该表对应的数据文件位置。
|
6月前
|
消息中间件 Java 关系型数据库
实时计算 Flink版操作报错合集之从 PostgreSQL 读取数据并写入 Kafka 时,遇到 "initial slot snapshot too large" 的错误,该怎么办
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
1022 0
|
6月前
|
DataWorks 安全 关系型数据库
DataWorks产品使用合集之使用Flink CDC读取PostgreSQL数据时如何指定编码格式
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
106 0
|
4月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
533 0
|
4月前
|
SQL 关系型数据库 HIVE
实时计算 Flink版产品使用问题之如何将PostgreSQL数据实时入库Hive并实现断点续传
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
开发框架 关系型数据库 数据库
在 PostgreSQL 中,解决图片二进制数据,由于bytea_output参数问题导致显示不正常的问题。
在 PostgreSQL 中,解决图片二进制数据,由于bytea_output参数问题导致显示不正常的问题。
|
6月前
|
关系型数据库 5G PostgreSQL
postgreSQL 导出数据、导入
postgreSQL 导出数据、导入
62 1