GaussDB中一种存储大数据的机制TOAST
TOAST是GaussDB中一种存储大数据的机制。TOAST表是否创建是根据原表列类型决定的,数据是否存到TOAST表中是根据数据大小决定的。创建原表时如果包含变长类型(text类型等)的列就会自动创建并关联TOAST表一张TOAST表负责行外存储,如下图8所示。GaussDB不允许一行数据跨页存储,当单个元组大小超过2K时,会自动触发TOAST机制,对数据进行压缩和切片,将实际数据存储到TOAST表。TOAST表不支持用户手动创建,随原表一起创建和删除。TOAST表和索引的存储类型和原表保持一致,原表和TOAST表通过OID关联,pg_class中原表会记录reltoastrelid(与原表关联的TOAST表的OID,如果没有则为0),在pg_class中通过OID可以找到TOAST表。
hashbucket TOAST数据管理方式
由于hashbucket扩容会将属于老节点的文件直接搬迁至新节点,此时如果TOAST指针中记录了老节点的OID信息,由于OID是本地维护的,搬迁到新节点可能出现访问不到数据的问题。因此,hashbucket表TOAST数据管理方式是由产生TOAST的列存储TOAST指针,存储小段页式1号文件的relfilenode。对TOAST表操作时通过小段页式1号文件SegmentHead页面的反向指针查询到当前hashbucket表大段页式1号文件的页面号,再通过反向指针获取到所属TOAST表的OID,如下图9所示:
数据插入时会先对可压缩的列执行压缩,然后判断元组长度是否能触发TOAST以及类型是否可以执行外部存储,多数情况下压缩后的元组长度不满足2K的阈值所以不会触发TOAST机制。访问数据时需要访问TOAST表中的压缩数据,对该数据解压。
关键数据结构TOAST指针varatt_external,存储获取行外存储数据所需的信息,数据结构设计如下:
typedef struct varatt_external {
int32 va_rawsize; /* 原始数据大小(包括header) */
int32 va_extsize; /* 外部保存大小(不包括header) */
Oid va_valueid; /* TOAST表中值的唯一id */
Oid va_toastrelid; /* toast表id */
} varatt_external;
其中va_extsize表示外部数据大小,va_rawsize表示原始未压缩数据大小,当且仅当va_extsize小于va_rawsize减var header大小时,数据会被压缩。以上内容从段页式技术方面对GaussDB高弹性能力进行了解读。