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. Java入门与进阶 P-3.5+P-3.6

    计数循环 这个循环需要执行多少次? 循环停下来的时候,有没有输出到最后的0 ? 循环结束后count的值是多少 算数平方 让用户输入一系列的正整数,最后输入-1标识输入结束,然后程序计算出这些数字的平 ...

  2. pycharm设置python头文件模版

    钢铁知识库,一个学习python爬虫.数据分析的知识库.人生苦短,快用python. 使用pycharm创建python文件时候,有时候需要自动生成想要的文件头,如何生成呢? 只需要以下几步: 在fi ...

  3. OpenStack命令行参考

    OpenStack命令行参考 hello,大家好,这里是费冰.在使用OpenStack的过程中,固然我们可以通过 web 页面完成绝大多数的操作,但作为管理人员,不能不知晓 OpenStack 命令行 ...

  4. 云服务器安装Mysql之后,设置可以进行远程连接,Duplicaticate wntry '%-root' for key 'PRIMARY

    云服务器安装Mysql之后,设置可以进行远程连接 1.首先连接mysql mysql -u root -p 2.MySql5版本 GRANT ALL ON *.* TO root@'%' IDENTI ...

  5. vue学习笔记(五)---- vue动画

    官方文档:https://cn.vuejs.org/v2/guide/transitions.html 一.使用过度类名 没有使用动画之前: <body> <div id=" ...

  6. 连接KingbaseES异常,致命错误/ 用户"system" Password 认证失败(kbjdbc/autodetected server-encoding to be GB2312...)

    com.kingbase8.util.KSQLException: 致命错误: 用户"system" Password 认证失败(kbjdbc:autodetected serve ...

  7. 为什么 TCP 建立连接需要三次握手(转载)

    为什么 TCP 建立连接需要三次握手(转载) 原文链接:https://draveness.me/whys-the-design-tcp-three-way-handshake/ TCP 协议是我们几 ...

  8. 线程、GIL、协程

    1.多进程实现TCP服务端并发 1.之前我们学习了一个服务端对应一个客户端的操作,但是我们无法实现一个服务端对应多个客户端的操作.因此我们需要在pycharm的右上角点击倒三角,选择Edit Conf ...

  9. KMP 算法 再次学习

    c++ 版后面再补 package cn.kbug.dynamic; import java.util.Arrays; /** * KMP 算法本质上是对 搜索的字符串做优化,然后在匹配的时候,能做到 ...

  10. Linux07-常用命令-权限

    1.组 1.1基本说明 在linux中的每个用户必须属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它组的概念. 1) 文件所有者 谁创建的这个文件,文件的所有者就是谁 2) 文 ...