PostgreSQL的TOAST技术

1.1 TOAST技术

  PostgreSQL数据页大小为8KB,且不允许行跨越多数据页;因此PostgreSQL不能直接存储较大的字段。所以PostgreSQL采用TOAST技术来存储大字段的值,TOAST针对大字段的值通常被压缩或切片成多个物理行存储在系统表TOAST表中,也就是行外存储。
  TOAST只支持特定的数据类型,因为对于小字段(整型、浮点数、时间等)是没有必要使用TOAST的。TOAST只支持变长的数据类型,在变长类型中,前4个字节(32bit)称为长度字,前2bit是标志位,一个表示是否压缩,一个表示是否行外存储;剩下的30bit表示数据的实际尺寸;长度字后面存储的是具体的内容或指针。
  如果一个表中有任何字段是可以TOAST的,则PostgreSQL会自动为该表建一个相关联的TOAST表,其中OID存储在表的pg_class.reltoastrelid记录里,行外的内容保存在TOAST表里。
  行外存储被切成多个chunk块,每个chunk块大约是一个block的1/4,每个chunk都作为独立的行在TOAST表中存储。每个TOAST表都有chunk_id、chunk_seq和chunk_data字段。在chunk_id、chunk_seq上有一个唯一的索引,用于提供对数值的快速检索。加上头部的长度字,一个TOAST指针数据的总长度是20字节。

  在PostgreSQL每个字段有四种TOAST的策略:

  • PLAIN:避免压缩和行外存储。只有那些不需要TOAST策略就能存放的数据类型允许选择(例如int类型),而对于text这类要求存储长度超过页大小的类型,是不允许采用此策略的。
  • EXTENDED:允许压缩和行外存储。一般会先压缩,如果还是太大,就会行外存储,大多数默认采用此策略。
  • EXTERNA:允许行外存储,但不许压缩。类似字符串这种会对数据的一部分进行操作的字段,采用此策略可能获得更高的性能,因为不需要读取出整行数据再解压。
  • MAIN:允许压缩,但不许行外存储。实际上,为了保证过大数据的存储,行外存储在其它方式(例如压缩)都无法满足需求的情况下,作为最后手段还是会被启动。因此理解为:尽量不使用行外存储。

1.2 PostgreSQL存储属性

  只有当数据大于2040字节时,才会触发TOAST压缩机制对数据进行压缩。在PostgreSQL11之前,2040字节这个限制是固定的,在PostgreSQL11之后,增加了存储参数toast_tuple_target控制这个值,例如:
alter table t1 set (toast_tuple_target=128);
  在PostgreSQL中,还有一些其他的存储属性,比如:fillfactortoast.fillfactor
fillfactor为表的存储因子;toast.fillfactor为TOAST表的存储因子。填充因子是10-100的整数,表示在插入数据时,在一个数据块中填充百分之几的空间后就不再填充,预留一部分空间,更新时再使用。在PostgreSQL中更新一条数据,原数据行不会立马被覆盖,如果块中有空闲空间,则新行直接插入这个数据块中,由于行仍然在数据块中,因此PostgreSQL可以使用Heap-Only Tuple技术,在原数据行与新数据行之间建立一个链表,这样一来就不需要更新索引了,索引项仍然会指向原数据行,然后通过链表找到最新数据。因为Heap-Only Tuple的链表不能跨数据块,如果新航必须插入新的数据块中,则无法使用该技术,这时需要更新表上的全部索引,会产生较大的消耗,所以需要对更新频繁的表设置较小的fillfactor

猜你喜欢

转载自blog.csdn.net/qq_42979842/article/details/112061430
今日推荐