TOAST表
简介
TOAST(The Oversized-Attribute Storage Technique)是一种特殊的存储机制。只有一些具有变长表现形式的数据才会支持TOAST,比如text类型。TOAST机制的主要目的是为了解决数据库中单个字段过大,无法直接存储在标准数据页中的问题。由于在GaussDB存储方式中,一条数据所有的字段组合在一起称为tuple,多个tuple组成一个page。page是数据在文件存储中的基本单位。GaussDB中的page默认大小为8KB,当某行数据大小超过page的大小时,数据库会启动TOAST,确保这些大字段能够被有效存储并管理。
行外存储是TOAST技术的一部分,该技术将大的字段压缩或切片成多个物理行存到另一张表(TOAST表),而主表只保留对这些大字段值的引用(通常是一个指针)。这样做的好处是,可以避免单行数据过大导致性能问题,同时仍然保持对大字段数据的有效访问。
如果某张表有一张关联的TOAST表,在PG_CLASS表里的reltoastrelid字段记录该TOAST表的OID,如果没有关联的TOAST表,reltoastrelid的值为0。
GaussDB中表的字段支持多种存储策略。有以下四种不同的存储策略:
- PLAIN:
- 不允许压缩和行外存储。这种策略通常用于不能使用TOAST机制的数据类型。
- 适用于不需要TOAST就能存放的数据类型,如整数类型、字符类型等。
- 对于存储长度超过page大小的类型(如text),不允许采用此策略。
- EXTENDED:
- 允许压缩和行外存储。这是大多数可以使用TOAST机制的数据类型的默认存储策略。
- 数据库会首先尝试对数据进行压缩,如果压缩后的数据仍然太大,则进行行外存储。
- EXTENDED是大多数可TOAST的数据类型默认策略,如text、bytea等。
- EXTERNAL:
- 允许行外存储,但不允许压缩。
- 这种策略可以使text、bytea数据类型的字符串操作更快,因为不需要读取和解压整行数据。
- MAIN:
- 允许压缩。
- 主要适用于numeric类型的数据。
- 数据库会首先尝试对数据进行压缩,如果压缩后的数据仍然太大,则进行行外存储。
示例
--建表。 gaussdb=# CREATE TABLE tb_t1(id int, info text); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'id' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE gaussdb=# CREATE TABLE tb_t2(id int, age int); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'id' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE --查看表tb_t1信息,info字段为text类型,且Storage为extended。 --部分回显内容如下: gaussdb=# \d+ tb_t1 Table "public.tb_t1" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+----------+--------------+------------- id | integer | | plain | | info | text | | extended | | --查看表tb_t2信息,所有字段为int类型。 --部分回显内容如下: gaussdb=# \d+ tb_t2 Table "public.tb_t2" Column | Type | Modifiers | Storage | Stats target | Description --------+-----------------------+-----------+----------+--------------+------------- id | integer | | plain | | age | integer | | plain | | --如下查询表示tb_t1有关联的TOAST表,tb_t2表没有关联的TOAST表。 gaussdb=# SELECT oid,relname,reltoastrelid FROM pg_class WHERE relname in ('tb_t1','tb_t2'); oid | relname | reltoastrelid -------+---------+--------------- 34519 | tb_t1 | 34522 34524 | tb_t2 | 0 (2 rows) --查询tb_t1关联的TOAST表信息。 gaussdb=# SELECT relname,oid FROM pg_class WHERE oid = '34522'; relname | oid ----------------+------- pg_toast_34519 | 34522 (1 row) --删除。 gaussdb=# DROP TABLE tb_t1,tb_t2; DROP TABLE