PG中的HOT(heap-only-tuple)机制

0    648    1

Tags:

👉 本文共约1815个字,系统预计阅读时间或需7分钟。

简介

由于MVCC的原因,pg并非是直接更新一行记录:它生成重复的记录并提供行的可见性映射信息。

为什么要这么做呢?因为数据库必须考虑一个关键问题:并发性。被更新的行可能还在被之前的事务使用。

为了解决这个问题:rdbms采用了不同技术:

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
  • 修改行,并将原来的行版本放置到另外一个地方。比如oracle中的undo

  • duplicate该行,通过行的可见性映射信息来标明行对哪个事务可见。这就需要一个清理机制来清理那些对所有事务都不再需要的行。这是通过pg中的vacuum来完成的。

下面借助pageinspect扩展来示例:

从结果可以看到,引擎duplicate了两行,vacuum清除的位置。

HOT(heap-only-tuple)机制

pg在8.3中,加入了HOT(heap-only-tuple)技术。使用HOT技术后,若所有索引属性都没有被修改(索引键是否修改是在执行时逐行判断的,因此如果一条update修改了某属性,但前后值相同则认为没有修改),且新版本与原来版本存在一个页面上则不会产生新的索引记录,因此这些记录被称为HOT(heap-only-tuple)。

hot会被打上heap_only_tuple标志,而HOT的上一个版本会被打上heap_hot_updated标志,然后顺着版本链向后找,直到遇到HOT为止。限制heap_only_tuple版本与hot在同一页面的目的是为了通过版本链向后找时不产生额外的io操作从而影响性能。因此,HOT技术消除了拥有完全相同键值的索引记录,减少了索引的大小。

使用Heap Only Tuples技术后,如果更新后的新行与旧行在同一个数据块内,旧行会有一个指针,指向新行,这样就不必更新索引了,当从索引访问到数据行时,会根据这个指针找到新行。

让我们来一个更复杂的案例:

再读取表的块:

表里含有两列,索引也含有两条记录指向对应的块(ctid)。

如果更新表的c1,对应的索引也会更新。

那如果更新表的c2,c1上的索引会被更新么?

乍一看,我们可能会说no,因为c1并没有被修改。

但是因为MVCC的存在,在理论上,回答应该是yes:从上面的例子可以看到数据库会duplicate记录行,因此物理位置会发生变化。

来看一下代码:

从表块信息可以看到,已经有了duplicated的行。看t_data就可以发现。

但是通过索引块来看,内容并没有改变。如果检索where c1=1,索引还是指向记录(0,1),对应老的记录。那这里究竟发生了什么呢?

事实上,我们刚才提到了heap-only-tuple机制。当一个列被更新,没有索引指向这个列,记录被插入相同的块,pg只是在老的记录和新的记录之间建立一个指针。这样就避免了更新索引,从而避免了:

1.避免读写操作

2.减少索引碎片和因为索引碎片导致的索引太大

通过上面的表的块查询结果,第一行的列t_ctid指向(0,3)。如果该行继续被更新,表的第一行会指向(0,3),而行(0,3)会指向(0,4),从而形成一个链条。vacuum会清空释放空间。

修改一行后,索引不会被修改:

使用vacuum清空:

一个更新会重利用第二个位置,但是索引仍然没有被修改。看下面的t_ctid列:

第一行是空的,pg利用了第三行的位置?实际上,pageinspect中没有包含一个信息,可以直接从pg_filedump中看出。

注意:你必须先请求一个checkpoint,否则块可能没有被写入磁盘

第一行包含Flags:REDIRECT,表示这行对应一个HOT重定向。可以从文档src/include/storage/itemid.h看出:

其实,通过pageinspect的lp_flags也可以看出:

如果我们继续更新,执行vacuum,并执行一个checkpoint:

pg继续保留第一行,并写入了新的第五行。

但是有些场景,pg并不能使用这种机制:

1.如果块已满,必须写入别的块。(HOT可以减少碎片)

2.如果更新的列上面有索引。这时,pg必须更新索引

参考

https://www.cnblogs.com/abclife/p/13194713.html

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部