干貨!PostgreSQL 從入門到提高 - 第24講:TOAST技術(shù)

PostgreSQL從小白到專家,是從入門逐漸能力提升的一個系列教程,內(nèi)容包括對PG基礎(chǔ)的認(rèn)知、包括安裝使用、包括角色權(quán)限、包括維護(hù)管理、、等內(nèi)容,希望對熱愛PG、學(xué)習(xí)PG的同學(xué)們有幫助,歡迎持續(xù)關(guān)注CUUG PG技術(shù)大講堂。
第24講:TOAST技術(shù)
內(nèi)容1 : Toast簡介
內(nèi)容2 : Toast的存儲方式
內(nèi)容3 : Toast4種壓縮策略
內(nèi)容4 : Toast表的計算方式
內(nèi)容5 : Toast表的優(yōu)點與缺點
內(nèi)容6 : 與Oracle大對象存儲方式對比
Toast簡介
· Toast技術(shù)產(chǎn)生背景
元組不允許跨頁面存儲
· TOST技術(shù)特點
Toast是超長字段在PG的一個存儲方式
全稱The OverSized Attribute Storage Technique(超尺寸字段存儲技術(shù))
它會將大字段值壓縮或者分散為多個物理行來存儲
對于用戶來說不用關(guān)注這一技術(shù)實現(xiàn),完全是透明的
Toast的存儲方式
· PG的部分類型數(shù)據(jù)支持toast,因為有些字段類型是不會產(chǎn)生大字段數(shù)據(jù)(比如date,time,boolean等)
· 支持Toast的數(shù)據(jù)類型應(yīng)當(dāng)是可變長度的(variable-length)
· 表中任何一個字段有Toast,這個表都會有這一個相關(guān)聯(lián)的Toast表,OID被存儲在pg_class.reltoastrelid里
· 超出的的數(shù)值將會被分割成chunks,并且最多toast_max_chunk_size 個byte(缺省是2KB)
· 當(dāng)存儲的列長度超過toast_tuple_threshold值(通常是2KB),就會觸發(fā)toast存儲
· toast將會壓縮或者移動字段值直到超出部分比toast_tuple_targer值小(這個值通常也是2KB)。
建表時自動創(chuàng)建Toast表
--創(chuàng)建表
create table toast_t(id int,vname varchar(48),remark text);
--其中remak數(shù)據(jù)類型是text,列值長度超過2KB則就會自動產(chǎn)生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
--根據(jù)tost表oid查看其名字
testdb=# select relname from pg_class where oid = '16389';
relname
----------------
pg_toast_16385
Toast4種策略
策略:PLAIN
說明:避免壓縮和行外存儲。
只有那些不需要 TOAST 策略就能存放的數(shù)據(jù)類型允許選擇(例如 int 類型),而對于 text 這類要求存儲長度超過頁大小的類型,是不允許采用此策略的。
策略:MAIN
說明:允許壓縮,但不許行外存儲。
不過實際上,為了保證過大數(shù)據(jù)的存儲,行外存儲在其它方式(例如壓縮)都無法滿足需求的情況下,作為最后手段還是會被啟動。因此理解為盡量不使用行外存儲更貼切。
策略:EXTENDED
說明:允許行外存儲和壓縮。
一般會先壓縮,如果還是太大,就會行外存儲
策略:EXTERNA
說明:允許行外存儲,但不許壓縮。
類似字符串這種會對數(shù)據(jù)的一部分進(jìn)行操作的字段,采用此策略可能獲得更高的性能,因為不需要讀取出整行數(shù)據(jù)再解壓。
Toast表額外的三個字段
字段名:chunk_id
屬性:標(biāo)識TOAST表的OID字段
字段名:chunk_seq
屬性:chunk的序列號,與chunk_id的組合唯一索引可以加速訪問
字段名:chunk_data
屬性:存儲TOAST表的實際數(shù)據(jù)
--查看tost表oid
testdb=# select relname,oid,rreltoastrelid from pg_class where relname='toast_t1';
relname | relfilenode | reltoastrelid
----------+-------------+---------------
toast_t1 | 16385 | 16389
--查看tost表結(jié)構(gòu),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表的計算
計算一個表的大小時要注意統(tǒng)計Toast的大小,因為對超長字段存儲時,在基礎(chǔ)表上可能只存了20%,另外的數(shù)據(jù)都存到了Toast里面去了,計算大小時要結(jié)合起來看
索引也是一樣,對于表里有extended或者EXTERNA 類型的會創(chuàng)建Toast表,兩者的關(guān)聯(lián)是通過pg_class里的OID去關(guān)聯(lián)的
· 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表的計算案例(二)
--插入數(shù)據(jù),此時remark列值長度小于2KB,所以不會觸發(fā)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表的計算案例(三)
--查看基礎(chǔ)表和 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,所以不會觸發(fā)tost存儲。
· Toast表的計算案例(四)
--remark列值超過 2kb 左右時觸發(fā)了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表的計算案例(五)
--查看各列的數(shù)據(jù)變化,說明在列尺寸超過2k的時候就會把數(shù)據(jù)存放到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表的計算案例(六)
--繼續(xù)插入更多的數(shù)據(jù):
insert into toast_t select generate_series(1,2),repeat('kenyon here'||'^_^',2),repeat('^_^ Kenyon is not God,Remark here!!',10000);
--查看toast表大?。?/p>
testdb=# select pg_size_pretty(pg_relation_size('16395'));
pg_size_pretty
----------------
16 kB
--繼續(xù)插入更多的數(shù)據(jù),20000
可以看到后插入的數(shù)據(jù)隨著字段內(nèi)容的增多,toast 段一直在變大?;A(chǔ)表的大小沒有變化。這個和 Oracle 存儲的大字段內(nèi)容比較像,Oracle 存儲 Blob和clob 類的數(shù)據(jù)時也是指定另外的 segment 來存儲,而不是在原表中存儲,當(dāng)然可以設(shè)置 enable storage in row 來指定表中存儲
Toast表的優(yōu)點
1.可以存儲超長超大字段,避免之前不能直接存儲的限制
2.物理上與普通表是分離的,檢索查詢時不檢索到該字段會極大地加快速度
3.更新普通表時,該表的Toast數(shù)據(jù)沒有被更新時,不用去更新Toast表
Toast表的缺點
1.對大字段的索引創(chuàng)建是一個問題,有可能會失敗,通常不建議在大字段上創(chuàng)建,全文檢索是一個解決方案
2.大字段的更新會有點慢,其它DB也存在相同問題
Oracle大對象段存儲特點
11g版本中推出了針對 LOB字段處理的新技術(shù):SecureFiles
該技術(shù)在性能、可管理性、易用性等方面,具有如下具體特點和優(yōu)勢:
· 提供數(shù)據(jù)去重、壓縮和透明加密功能
· SecureFiles不僅可以有效降低LOB字段存儲空間消耗,提高了訪問效率,而且提高了LOB字段的數(shù)據(jù)安全性。
以上述某系統(tǒng)為例,我們將其中一個100GB的LOB字段轉(zhuǎn)換為SecureFiles,并采用壓縮技術(shù)之后,最終只消耗30GB空間,大大壓縮了存儲空間。
·新的網(wǎng)絡(luò)協(xié)議
SecureFiles提供一種新的Client/Server方式的內(nèi)部讀寫機(jī)制,有效提高了大量數(shù)據(jù)傳輸?shù)男省?/p>
· 簡化物理屬性設(shè)計和管理
SecureFiles提供了大量自動化的物理屬性機(jī)制,免去了大量物理屬性設(shè)計和管理工作。例如:CHUNK屬性為可變長,最大能支持到64M;Oracle能自動進(jìn)行碎片整理;
· SecureFiles還自動進(jìn)行redo和undo的管理,避免大量不必要的redo和 undo信息的產(chǎn)生。

以上就是【PostgreSQL從小白到專家】第24講 - TOAST技術(shù)? 的內(nèi)容,歡迎一起探討交流釘釘交流群:35,82,24,60,往期視頻及文檔內(nèi)容聯(lián)系CUUG