PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。
第24讲:TOAST技术
内容1 : Toast简介
内容2 : Toast的存储方式
内容3 : Toast4种压缩策略
内容4 : Toast表的计算方式
内容5 : Toast表的优点与缺点
内容6 : 与Oracle大对象存储方式对比
Toast简介
· Toast技术产生背景
元组不允许跨页面存储
· TOST技术特点
Toast是超长字段在PG的一个存储方式
全称The OverSized Attribute Storage Technique(超尺寸字段存储技术)
它会将大字段值压缩或者分散为多个物理行来存储
对于用户来说不用关注这一技术实现,完全是透明的
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表
--创建表
create table toast_t(id int,vname varchar(48),remark text);
--其中remak数据类型是text,列值长度超过2KB则就会自动产生toast表来存储。
更改表的存储方式为Toast
语法:
ALTER TABLE toast_t ALTER COLUMN vname
SET STORAGE {PLAIN | EXTENDED | MAIN | EXTERNAL};
示例:
create table toast_t1(dd character varying);
alter table toast_t1 alter column dd set storage main;
/d toast_1
Column | Type | Storage |
-------- ----- --------- -
dd | character varying | main |
Access method: heap
查看Toast表的名字
--查看tost表的oid
testdb=# select relname,relfilenode,reltoastrelid from pg_class where relname='toast_t1';
relname | relfilenode | reltoastrelid
---------- ------------- ---------------
toast_t1 | 16385 | 16389
--根据tost表oid查看其名字
testdb=# select relname from pg_class where oid = '16389';
relname
----------------
pg_toast_16385
Toast4种策略
策略:PLAIN
说明:避免压缩和行外存储。
只有那些不需要 TOAST 策略就能存放的数据类型允许选择(例如 int 类型),而对于 text 这类要求存储长度超过页大小的类型,是不允许采用此策略的。
策略:MAIN
说明:允许压缩,但不许行外存储。
不过实际上,为了保证过大数据的存储,行外存储在其它方式(例如压缩)都无法满足需求的情况下,作为最后手段还是会被启动。因此理解为尽量不使用行外存储更贴切。
策略:EXTENDED
说明:允许行外存储和压缩。
一般会先压缩,如果还是太大,就会行外存储
策略:EXTERNA
说明:允许行外存储,但不许压缩。
类似字符串这种会对数据的一部分进行操作的字段,采用此策略可能获得更高的性能,因为不需要读取出整行数据再解压。
Toast表额外的三个字段
字段名:chunk_id
属性:标识TOAST表的OID字段
字段名:chunk_seq
属性:chunk的序列号,与chunk_id的组合唯一索引可以加速访问
字段名:chunk_data
属性:存储TOAST表的实际数据
--查看tost表oid
testdb=# select relname,oid,rreltoastrelid from pg_class where relname='toast_t1';
relname | relfilenode | reltoastrelid
---------- ------------- ---------------
toast_t1 | 16385 | 16389
--查看tost表结构,tost表属于pg_tost模式
testdb=# d pg_toast.pg_toast_16385
Column | Type | Storage
------------ --------- ---------
chunk_id | oid | plain
chunk_seq | integer | plain
chunk_data | bytea | plain
Toast表的计算
计算一个表的大小时要注意统计Toast的大小,因为对超长字段存储时,在基础表上可能只存了20%,另外的数据都存到了Toast里面去了,计算大小时要结合起来看
索引也是一样,对于表里有extended或者EXTERNA 类型的会创建Toast表,两者的关联是通过pg_class里的OID去关联的
· Toast表的计算案例(一)
testdb=# create table toast_t(id int,vname varchar(48),remark text);
CREATE TABLE
testdb=# select relname,oid from pg_class where relname = 'toast_t';
relname | oid
--------- -------
toast_t | 16392
testdb=# select relname,reltoastrelid from pg_class where relname = 'toast_t';
relname | reltoastrelid
--------- ---------------
toast_t | 16395
testdb=# select relname from pg_class where oid = '16395';
relname
----------------
pg_toast_16392
· Toast表的计算案例(二)
--插入数据,此时remark列值长度小于2KB,所以不会触发tost存储:
insert into toast_t
select generate_series(1,4),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',2000);
--查看表中列值大小:
testdb=# select pg_column_size(id),pg_column_size(vname),pg_column_size(remark) from toast_t limit 10;
pg_column_size | pg_column_size | pg_column_size
---------------- ---------------- ----------------
4 | 29 | 851
4 | 29 | 851
4 | 29 | 851
4 | 29 | 851
· Toast表的计算案例(三)
--查看基础表和 Toast 的大小
testdb=# select pg_size_pretty(pg_relation_size('toast_t'));
pg_size_pretty
----------------
8192 bytes
--查看tost表尺寸
testdb=# select pg_size_pretty(pg_relation_size('16395'));
pg_size_pretty
----------------
0 bytes
此时remark列值长度小于2KB,所以不会触发tost存储。
· Toast表的计算案例(四)
--remark列值超过 2kb 左右时触发了tost存储方式
insert into toast_t select generate_series(3,4),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',5500);
testdb=# select pg_size_pretty(pg_relation_size('16395'));
pg_size_pretty
----------------
8192 bytes
· Toast表的计算案例(五)
--查看各列的数据变化,说明在列尺寸超过2k的时候就会把数据存放到toast表中:
testdb=# select pg_column_size(id),pg_column_size(vname),pg_column_size(remark) from toast_t;
pg_column_size | pg_column_size | pg_column_size
---------------- ---------------- ----------------
4 | 29 | 851
4 | 29 | 851
4 | 29 | 851
4 | 29 | 851
4 | 29 | 1651
4 | 29 | 1651
4 | 29 | 2247
4 | 29 | 2247
· Toast表的计算案例(六)
--继续插入更多的数据:
insert into toast_t select generate_series(1,2),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',10000);
--查看toast表大小:
testdb=# select pg_size_pretty(pg_relation_size('16395'));
pg_size_pretty
----------------
16 kB
--继续插入更多的数据,20000
可以看到后插入的数据随着字段内容的增多,toast 段一直在变大。基础表的大小没有变化。这个和 Oracle 存储的大字段内容比较像,Oracle 存储 Blob和clob 类的数据时也是指定另外的 segment 来存储,而不是在原表中存储,当然可以设置 enable storage in row 来指定表中存储
Toast表的优点
1.可以存储超长超大字段,避免之前不能直接存储的限制
2.物理上与普通表是分离的,检索查询时不检索到该字段会极大地加快速度
3.更新普通表时,该表的Toast数据没有被更新时,不用去更新Toast表
Toast表的缺点
1.对大字段的索引创建是一个问题,有可能会失败,通常不建议在大字段上创建,全文检索是一个解决方案
2.大字段的更新会有点慢,其它DB也存在相同问题
Oracle大对象段存储特点
11g版本中推出了针对 LOB字段处理的新技术:SecureFiles
该技术在性能、可管理性、易用性等方面,具有如下具体特点和优势:
· 提供数据去重、压缩和透明加密功能
· SecureFiles不仅可以有效降低LOB字段存储空间消耗,提高了访问效率,而且提高了LOB字段的数据安全性。
以上述某系统为例,我们将其中一个100GB的LOB字段转换为SecureFiles,并采用压缩技术之后,最终只消耗30GB空间,大大压缩了存储空间。
·新的网络协议
SecureFiles提供一种新的Client/Server方式的内部读写机制,有效提高了大量数据传输的效率。
· 简化物理属性设计和管理
SecureFiles提供了大量自动化的物理属性机制,免去了大量物理属性设计和管理工作。例如:CHUNK属性为可变长,最大能支持到64M;Oracle能自动进行碎片整理;
· SecureFiles还自动进行redo和undo的管理,避免大量不必要的redo和 undo信息的产生。
以上就是【PostgreSQL从小白到专家】第24讲 - TOAST技术 的内容,欢迎一起探讨交流