行链接和toast

举报
宁谷花雨 发表于 2024/08/28 19:23:23 2024/08/28
【摘要】 1、1)行迁移:    当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移。一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址。因此整行数据都被移动,原始的数据块上仅仅保留的是指向新块的一个地址信息。 2)迁移行不影响全表扫描    当使用全表扫描时,转移地址被忽略。因为我们最终能够获得所有的数据,所以能够忽略其转移地址。因此行迁移并...

1、

1)行迁移:

    当一个行上的更新操作(原来的数据存在且没有减少)导致当前的数据不能在容纳在当前块,我们需要进行行迁移。一个行迁移意味着整行数据将会移动,仅仅保留的是一个转移地址。因此整行数据都被移动,原始的数据块上仅仅保留的是指向新块的一个地址信息。

 2)迁移行不影响全表扫描

    当使用全表扫描时,转移地址被忽略。因为我们最终能够获得所有的数据,所以能够忽略其转移地址。因此行迁移并不会对全表扫描产生额外的操作。

  迁移行对索引读产生额外的I/O:当使用索引读取数据时将产生额外的I/O。这是由于索引告诉我们通过文件X,块Y,slot槽Z可以获得该行数据。但是当我们根据地址信息达到所在位置时,从其转移地址得知,其真实的数据是存储在文件A,块B,slot槽C上。因此为了寻找该行数据不得不产生额外的逻辑或物理I/O。

 3)行链接:当一行数据太大而不能在一个单数据块容纳时,行链接由此产生。行链接有着不同于行迁移的影响,取决于我们所需的数据。如果我们有一行数据有两个列且跨越两个数据块。

 4)行迁移影响OLTP系统使用索引读取单行。最糟糕的情形所对所有的读都增加额外的I/O。而行链接则影响索引读和全表扫描。

基于行链接或行迁移的查询或创建(如索引)由于需要更多的I/O将降低数据库的性能。

移出行链接或行迁移使用更大的pctfree参数或使用alter table move命令。

  

5)Oracle似乎是从后向前进行的写操作,Oracle存储数据是从后往前的,比如一行数据分配了 block #1,2,3,那么存储起来就是先写3,然后2,写不下了再写1 之所以这样说是因为这个块被写满了,而前一块并没有被写满。根据两个BLOCK结构的分析,基本上确认了文章开始的分析,也就是Oracle一个块无法写下全部记录的时候,会通过行链接实现,而实现的方式就是在块头处通过ROWID的方式之处下一个存放记录的块的位置。

 

6)Oracle并不是以列作为划分记录的单位,一列的数据可能分布到多个BLOCK上,比如这个例子。那么Oracle是如何确定当前BLOCK存放最后一列记录是否完整呢?

所有的块头都包括H和F,而所有的结尾块都包含L,那么显然H或者F标识的是行头信息,而L标识行尾信息。推测H这里表示HIGN END或者HEADING,而L表示LOW END或者LEAF。如果当前块包含的最后一个COLUMN的内容没有结束,会在标识中包含一个N,应该表示NEXT的含义。而对应的下一个BLOCK,如果列不是从头开始,会在标识中包含一个P,应该是PRIOR的含义。

  

https://www.cnblogs.com/buro79xxd/archive/2011/02/16/1956327.html

https://cloud.tencent.com/developer/article/1953001

  

2、postgresql toast

Toast 在存储大型数据时,会将它存储在单独的表中(称为 toast 表)。postgresql 不允许 tuple 跨页存储,所以当一行数据的某个列数据过大时,比如 text 类型的数据,超过了单页的大小,那么 postgresql 会将它压缩,切分,并且存储在另外的位置。这种技术就是称为 Toast。

 

toast表字段:chunk_idchunk_seqchunk_data 索引为chunk_id + chunk_seq

 

假设现在向 mytable 表插入一条大型数据,长度为3MB,里面存储了一张图片,采用了base64格式。

postgresql 在处理这条请求时,发现 name 是 text 类型,并且这次插入的数据过大。那么首先它会被压缩,假设被压缩成 1MB,压缩后仍然不满足大小,然后按照指定的大小(默认为 2048 byte)切分成 512 份。每一份切片对应 toast 表的一行数据,它们的 chunk_id 都是相同的,因为属于同一个数据,只是 chunk_seq 不同,对应着切片位置。chunk_data 列就是存储着切片的数据。

  

3、

postgresql 并没有使用跨页存储的方案,而是将大型数据单独放到其余地方存储。这样在条件过滤时,会比较好,因为它不需要读取这些大的数据,而且只有当该列被选中时,才会在返回数据时去读取。这种场景下,减少了磁盘 IO 的读取,提升了性能。

 

同样它也有对应的缺点,那就是写入大型的数据时,会比较慢。因为它需要切片,然后插入到 toast 表中,还要更新 toast 表的索引。

如果采用跨页存储,那么还可以利用磁盘顺序写的高性能。

在读取整行数据时候,还需要先去寻找 toast 表的索引,然后再去读取 toast 表的数据,相比较跨页存储,仍然无法使用磁盘顺序读的高性能。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。