PostgreSQL数据库不允许元组(行,记录)跨越多个页面(page)存储,所以,它不能直接存储非常大的字段值。对于大字段值,它将被压缩且(或)分解为多个物理行,该技术称为“TOAST”。

toast技术特点

  1. toast是超长字段在PG的一个存储方式;
  2. 全称The overSized Attribute Stroage Technique(超尺寸字段存储技术);
  3. 它会将大字段值压缩或者分散为多个物理行来存储;
  4. 对于用户来说不用关注这一技术实现,完全是透明的;

toast的存储方式

  • pg的部分类型数据支持toast,因为有些字段类型是不会产生大字段数据(比如date,time,boolean);
  • 支持toast的数据类型应当是可变长度的(variable-length);
  • 表中任何一个字段有toast,这个表都会有一个相关联的toast表,oid被存储在pg_class.reltoastrelid里;
  • 超出的数值会被分割成chunks,并且最多toast_max_chunk_size个byte(缺省是2KB);
  • 当存储的长度超过toast_tuple_threshold(通常是2KB),就会触发toast存储;
  • toast将会压缩或者移动字段值直到超过部分比toast_tuple_targer值小(这个值通常也是2KB)

建表时自动创建toast表

dellstore2=# create table toast_1(id int);
CREATE TABLE dellstore2=# select oid,relname,reltoastrelid from pg_class where relname = 'toast_1';
oid | relname | reltoastrelid
-------+---------+---------------
16498 | toast_1 | 0
(1 row) dellstore2=# create table toast_2(id int,info text);--其中info字段是text类型,则会自动产生toast表来存储。
CREATE TABLE
dellstore2=# select oid,relname,reltoastrelid from pg_class where relname = 'toast_2';
oid | relname | reltoastrelid
-------+---------+---------------
16501 | toast_2 | 16504
(1 row) dellstore2=# select oid,relname from pg_class where oid = 16504;
oid | relname
-------+----------------
16504 | pg_toast_16501
(1 row)

更改表的存储方式为toast

语法:

ALTER TABLE [ TABLE ] ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }

dellstore2=# create table toast_0(info text);
CREATE TABLE
dellstore2=# \d+ toast_0
Table "public.toast_0"
Column | Type | Modifiers | Storage | Stats target | Description
--------+------+-----------+----------+--------------+-------------
info | text | | extended | | dellstore2=# alter table toast_0 alter column info set storage main;
ALTER TABLE
dellstore2=# \d+ toast_0
Table "public.toast_0"
Column | Type | Modifiers | Storage | Stats target | Description
--------+------+-----------+---------+--------------+-------------
info | text | | main | |

查看toast表的名字

dellstore2=# select relname,relfilenode,reltoastrelid from pg_class where relname = 'toast_0';
relname | relfilenode | reltoastrelid
---------+-------------+---------------
toast_0 | 16507 | 16510
(1 row) dellstore2=# select relname from pg_class where oid = 16510;
relname
----------------
pg_toast_16507
(1 row)

toast四种存储策略

策略 说明
PLAIN 避免压缩和行外存储。只有那些不需要TOAST策略就能存放的数据类型允许选择(例如 int类型),而对于text这类要求存储长度超过页大小的类型,是不允许采用此策略的
MAIN 允许压缩,但不许行外存储。实际上,为了保证大数据的存储,行外存储在其他方式(例如压缩)都无法满足的情况下,作为最后手段还是会被启动。因此理解为尽量不使用行外存储更贴切
EXTENDED 允许行外存储和压缩。一般会压缩,如果还是太大,就会行外存储
EXTERNA 允许行外存储,但不允许压缩。类似字符串这种会对数据的一部分进行操作的字段,采用此策略可能获得更高的性能,因为不需要读取整行数据再解压

toast表额外的三个字段

字段名 属性
chunk_id 标识TOAST表的OID字段
chunk_seq chunk的序列号,与chunk_id的组合唯一索引可以加速访问
chunk_data 存储TOAST表的实际数据
dellstore2=# select oid,relname,reltoastrelid from pg_class where relname = 'toast_0';
oid | relname | reltoastrelid
-------+---------+---------------
16507 | toast_0 | 16510
(1 row) dellstore2=# \d+ toast_0
Table "public.toast_0"
Column | Type | Modifiers | Storage | Stats target | Description
--------+------+-----------+---------+--------------+-------------
info | text | | main | |

toast表的计算

  • 计算一个表的大小时要注意统计toast的大小,因为对超长字段存储时,在基础表上可能只存了20%,另外的数据都存到了toast表里面去了,计算大小时要结合起来看
  • 索引也是一样,对于表里有extended或者EXTERNA类型的会创建toast表,两者的关联是通过pg_class里的OID取关联的
dellstore2=# create table toast_t(id int,name varchar(50),info text);
CREATE TABLE
dellstore2=# select relname,relfilenode,reltoastrelid from pg_class where relname = 'toast_t';
relname | relfilenode | reltoastrelid
---------+-------------+---------------
toast_t | 16513 | 16516
(1 row) dellstore2=# insert into toast_t select generate_series(1,2),'test',repeat('t',10000);
INSERT 0 2
dellstore2=# select pg_column_size(id),pg_column_size(name),pg_column_size(info) from toast_t;
pg_column_size | pg_column_size | pg_column_size
----------------+----------------+----------------
4 | 5 | 125
4 | 5 | 125
(2 rows) dellstore2=# select pg_size_pretty(pg_relation_size('toast_t')),pg_size_pretty(pg_relation_size(16516));
pg_size_pretty | pg_size_pretty
----------------+----------------
8192 bytes | 0 bytes
(1 row) dellstore2=# insert into toast_t select generate_series(1,2),'test',repeat('t',100000);
INSERT 0 2
dellstore2=# select pg_size_pretty(pg_relation_size('toast_t')),pg_size_pretty(pg_relation_size(16516));
pg_size_pretty | pg_size_pretty
----------------+----------------
8192 bytes | 0 bytes
(1 row) dellstore2=# insert into toast_t select generate_series(1,2),'test',repeat('t',200000);
INSERT 0 2
dellstore2=# select pg_size_pretty(pg_relation_size('toast_t')),pg_size_pretty(pg_relation_size(16516));
pg_size_pretty | pg_size_pretty
----------------+----------------
8192 bytes | 8192 bytes
(1 row) dellstore2=# insert into toast_t select generate_series(1,2),'test',repeat('t',400000);
INSERT 0 2
dellstore2=# select pg_size_pretty(pg_relation_size('toast_t')),pg_size_pretty(pg_relation_size(16516));
pg_size_pretty | pg_size_pretty
----------------+----------------
8192 bytes | 16 kB
(1 row)

可以看到后插入的数据随着字段内容的增多,toast段一直在变大。基础表的大小没有变化。

toast表的优点

  1. 可以存储超长大字段,避免之前不能直接存储的限制;
  2. 物理上与普通表是分离的,检索查询时不检索到该字段会极大地加快速度;
  3. 更新普通表时,该表地toast数据没有被更新时,不用去更新toast表

toast表的缺点

  1. 对大字段的索引创建是一个问题,有可能会失败,通常不建议在大字段上创建,全文检索是一个解决方案
  2. 大字段的更新会有点慢, 其他DB也存在相同问题

toast简介的更多相关文章

  1. Android Toast简介

    Toast是Android中一种提供给用户简短信息的视图,该视图已浮于应用程序之上的形式呈现给用户.因为它并不获得焦点,即使用户正在输入什么也不会受到影响.它的目标是尽可能以不显眼的方式,使用户看到你 ...

  2. Android带图片的Toast(自定义Toast)

    使用Android默认的Toast Toast简介: Toast是一个简单的消息显示框,能够短暂的出现在屏幕的某个位置,显示提示消息. 默认的位置是屏幕的下方正中,一般Toast的使用如下: Toas ...

  3. 【UWP开发】一个简单的Toast实现

    Toast简介 在安卓里Toast是内置原生支持,它是Android中用来显示显示信息的一种机制.它主要用于向用户显示提示消息,没有焦点,显示的时间有限,过一定的时间就会自动消失.在UWP中虽然没有原 ...

  4. [UWP 开发] 一个简单的Toast实现

    Toast简介 在安卓里Toast是内置原生支持,它是Android中用来显示显示信息的一种机制.它主要用于向用户显示提示消息,没有焦点,显示的时间有限,过一定的时间就会自动消失.在UWP中虽然没有原 ...

  5. appium应用切换以及toast弹出框处理

    一.应用切换 应用切换的方法很简单,直接调用driver.start_activity()方法,传入app_package和app_activity参数,示例代码如下: from appium imp ...

  6. Appium之Toast元素识别

    问题思考 在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,那么我们该如何获取这些元素文字内容呢? Toast简介 Android中的 ...

  7. python+Appium自动化:toast定位

    Toast简介 Toast是一种简易的消息提示框. 当视图显示给用户,在应用程序中显示为浮动.和Dialog不一样的是,它永远不会获得焦点,无法被点击. 用户将可能是在中间键入别的东西.Toast类的 ...

  8. OS快速开发必备

    github:https://github.com/koknine (终于改成以前的了) 当前移动互联网行业太火爆,移动端的需求日益增长,很多开发人员每天都应对着各种需求,作为一名iOS开发人员,对于 ...

  9. Tost元素识别

    在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,那么我们该如何获取这些元素文字内容呢? Toast简介 Android中的Toast ...

  10. Appium+python自动化(二十六)- 烟花一瞬,昙花一现 -Toats提示(超详解)

    简介 今天宏哥在这里首先给小伙伴们和童鞋们分享一个有关昙花的小典故:话说昙花原是一位花神,她每天都开花,四季都灿烂.她还爱上了每天给她浇水除草的年轻人.后来,此事给玉帝得知.于是,玉帝大发雷霆,要拆散 ...

随机推荐

  1. 分布式协议与算法-Raft算法

    本文总结自:极客时间韩健老师的分布式协议与算法实战课程. 大家都知道,Raft算法属于Multi-Paxos算法,它是在Multi-Paxos思想的基础上,做了一些简化和限制.关于Paxos算法,博主 ...

  2. 简述 Gin 框架如何集成swagger

    https://blog.csdn.net/raogeeg/article/details/86743953 @Title           这个 API 所表达的含义,是一个文本,空格之后的内容全 ...

  3. Lodop打印小票

    使用Lodop打印小票 1.html页面 <head> <meta http-equiv="Content-Type" content="text/ht ...

  4. .NET Core 项目启动时运行定时任务

    1.任务需求 在每次服务启动时定时(如24小时)清理一次缓存文件 2.代码实现 1)新建文件清理类 .NET Core 提供了BackgroundService的抽象类,在 ExecuteAsync ...

  5. Vue搭建项目的完整流程 如何搭建一个完整的vue项目 vue项目架构

    vue项目架构 技术栈:vue3.vue-router .vuex(和pinia).element plus .axios.ts.sass 1.安装vue3 脚手架+ ts vue create ad ...

  6. 安卓逆向 IDA 动态调试 案例1

    adb forward tcp:23946 tcp:23946 adb devices adb shell su cd /data/local/tmp ./android_server adb she ...

  7. Openfoam Pstream类探索

    对于数值仿真而言,无论是商软或者开源并行计算都是非常重要的,而且想把自身数值仿真能力提升一个层次,必须对并行计算有很好的理解与应用 openfoam并行通信主要通过Pstream类完成 本篇文章进行说 ...

  8. [USACO06NOV] Round Numbers S

    题目 \(\texttt{[USACO06NOV] Round Numbers S}\) 分析 数位 \(dp\) 入门题 一般我们需要当前位置 \(pos\),有无前导零 \(lead\),高位标记 ...

  9. Linux命令-用户、权限管理

      Linux命令-用户.权限管理 用户是Unix/Linux系统工作中重要的一环,用户管理包括用户与组账号的管理. 在Unix/Linux系统中,不论是由本机或是远程登录系统,每个系统都必须拥有一个 ...

  10. 解决veture和eslint冲突的问题

    vscoder自带的veture和eslint存在冲突,主要表现在 末尾逗号,分号,单双引号的不一致.解决办法:1.npm install --save-dev prettier2.在根目录新建.pr ...