【PostgreSQL的变长字段数据超过多少会写入到TOSAST表】

2024-03-12 14:28

本文主要是介绍【PostgreSQL的变长字段数据超过多少会写入到TOSAST表】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常PostgreSQL里如果一个元祖的变长字段的数据量,超过2KB,则PostgreSQL会尝试进行压缩,把元组控制在2KB之内,如果不能满足2KB之内的需求,就需要独立的toast表来存储了。

一、toast表相关的列存储参数

这个是否尝试压缩是受列上的Storage这一参数决定的,如果想要用toast但是又不想压缩,可以把列的storage参数设置为external。

postgres=# \d+ test_toast Table "public.test_toast"Column |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description 
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------id     | integer |           |          |         | plain    |             |              | name   | text    |           |          |         | extended |             |              | 
Access method: heap

这个列的存储策略有如下四个可供调整的值。

plain:该列仅存储在堆中且未压缩。
extended:如有必要,可以压缩该列并将其存储在 toast 中。
external:该列可以存储在 toast 中,但不能压缩。有时,可以使用此模式以更高的磁盘空间消耗为代价来提高性能(避免压缩/解压缩)。
main:该列仅存储在堆中,但与普通模式不同,允许压缩。

对于某类字段的默认存储类型,pg_type的typstorage中有明确的定义

postgres=# select typname,typstorage from pg_type where typname in ('int4','text','');typname | typstorage 
---------+------------int4    | ptext    | x
(2 rows)

可以用如下方式进行调整

postgres=# alter table test_toast alter column name set storage external;
ALTER TABLE
postgres=#  \d+ test_toast Table "public.test_toast"Column |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description 
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------id     | integer |           |          |         | plain    |             |              | name   | text    |           |          |         | external |             |              | 
Access method: heap

二、2KB的大小如何是如何计算的

这个2KB的阈值其实受源码里的TOAST_TUPLE_THRESHOLD限制的,

/** These symbols control toaster activation.  If a tuple is larger than* TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than* TOAST_TUPLE_TARGET bytes through compressing compressible fields and* moving EXTENDED and EXTERNAL data out-of-line.** The numbers need not be the same, though they currently are.  It doesn't* make sense for TARGET to exceed THRESHOLD, but it could be useful to make* it be smaller.** Currently we choose both values to match the largest tuple size for which* TOAST_TUPLES_PER_PAGE tuples can fit on a heap page.** XXX while these can be modified without initdb, some thought needs to be* given to needs_toast_table() in toasting.c before unleashing random* changes.  Also see LOBLKSIZE in large_object.h, which can *not* be* changed without initdb.*/
#define TOAST_TUPLES_PER_PAGE	4#define TOAST_TUPLE_THRESHOLD	MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)#define TOAST_TUPLE_TARGET		TOAST_TUPLE_THRESHOLD

根据代码定义可以看到:

TOAST_TUPLE_THRESHOLD = MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)

而MaximumBytesPerTuple函数的定义如下:

/** Find the maximum size of a tuple if there are to be N tuples per page.*/
#define MaximumBytesPerTuple(tuplesPerPage) \MAXALIGN_DOWN((BLCKSZ - \MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \/ (tuplesPerPage))

在C语言代码里,我们有时会遇到一行代码太长而影响阅读或者与要求的编码规范不符的情况,此时需要将这行代码分成多行来写。在编译时,\后面的换行符将被忽略,当做一行处理。

所以

MaximumBytesPerTuple(tuplesPerPage) = MAXALIGN_DOWN((BLCKSZ - MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) / (tuplesPerPage))TOAST_TUPLE_THRESHOLD 
= MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
= MAXALIGN_DOWN((BLCKSZ - MAXALIGN(SizeOfPageHeaderData + (TOAST_TUPLES_PER_PAGE) * sizeof(ItemIdData))) / (TOAST_TUPLES_PER_PAGE))

而定义里TOAST_TUPLES_PER_PAGE=4,并且默认BLCKSZ = 8KB

PageHeaderData --在 page 头部,24 个字节长度,记录 page 的元数据信息。所以SizeOfPageHeaderData= 24 bytes

ItemIdData --在 page header 之后,一个记录(偏移量,长度)对的数组,指向实际 tuple 项,每个 4 字节。所以sizeof(ItemIdData)=4 bytes

所以上述的TOAST_TUPLE_THRESHOLD可以转换为下边

TOAST_TUPLE_THRESHOLD
= MAXALIGN_DOWN((BLCKSZ - MAXALIGN(24bytes  + 4 * 4bytes)) / 4= MAXALIGN_DOWN((8KB - MAXALIGN(24bytes + 4 * 4bytes)) / 4~=2KB

因此如果变长字段的storage参数为external,表字段很长存储超过2KB的时候,就会触发行外存储,把数据存储到toast表里。如果是extended则会尝试进行压缩,把元祖控制在2KB之内,如果不能满足2KB之内的需求,就需要独立的toast表来存储。

三、如何调整元祖存储到toast表的这个阈值

如果对于2KB的设置觉得不符合需求的话,可以修改源码中的TOAST_TUPLE_THRESHOLD定义,再编译。不过这种静态编译比较麻烦。

而针对这一问题,PostgreSQL11版本增加了一个特性,支持表级动态设TOAST_TUPLE_THRESHOLD,这样就不需要调整源码实现了,也更加灵活了。

调整的语法如下,单位是bytes

postgres=# alter table test_toast  set (toast_tuple_target = 4096);  
ALTER TABLE
postgres=# \d+ test_toast Table "public.test_toast"Column |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description 
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------id     | integer |           |          |         | plain    |             |              | name   | text    |           |          |         | external |             |              | 
Access method: heap
Options: toast_tuple_target=4096

这篇关于【PostgreSQL的变长字段数据超过多少会写入到TOSAST表】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/801556

相关文章

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

postgresql数据库基本操作及命令详解

《postgresql数据库基本操作及命令详解》本文介绍了PostgreSQL数据库的基础操作,包括连接、创建、查看数据库,表的增删改查、索引管理、备份恢复及退出命令,适用于数据库管理和开发实践,感兴... 目录1. 连接 PostgreSQL 数据库2. 创建数据库3. 查看当前数据库4. 查看所有数据库

Navicat数据表的数据添加,删除及使用sql完成数据的添加过程

《Navicat数据表的数据添加,删除及使用sql完成数据的添加过程》:本文主要介绍Navicat数据表的数据添加,删除及使用sql完成数据的添加过程,具有很好的参考价值,希望对大家有所帮助,如有... 目录Navicat数据表数据添加,删除及使用sql完成数据添加选中操作的表则出现如下界面,查看左下角从左

SpringBoot中4种数据水平分片策略

《SpringBoot中4种数据水平分片策略》数据水平分片作为一种水平扩展策略,通过将数据分散到多个物理节点上,有效解决了存储容量和性能瓶颈问题,下面小编就来和大家分享4种数据分片策略吧... 目录一、前言二、哈希分片2.1 原理2.2 SpringBoot实现2.3 优缺点分析2.4 适用场景三、范围分片