本文转载自公众号“数据库架构之美”
我们知道在数据库行数据更新时,索引也需要进行维护,如果是高并发的情况下,索引维护的代价很大,可能造成索引分裂。Pg为了避免这个问题,采用了HOT(堆内元组技术)解决这个问题,下面我们就这个技术详细探讨一下。
我们先看看postgresql中page的结构:

pd_lsn:本页面最后一次变更所写入的xlog记录对应的lsn。
pd_checksum:页面校验和。
pd_lower:指向行指针的末尾(空闲空间开始位置)。
pd_upper:指向最新堆元组的起始位置(空闲空间结束位置)。
pd_special:用在索引页中,在索引页中它指向特殊空间的起始位置,在堆表页面中它指向页尾。
pd_pagesize_version:页面大小以及页面布局的版本号。
pd_prune_xid:本页面可以修剪的最老元组的xid。
从上面的结构我们可以看到,pd_lower和pd_upper分别指向空闲空间的起始和终止位置,而图中的1和2是行指针,分别指向真实的元组位置。
了解了page的结构后我们再来看看元组的结构:

t_mix:插入此元组的事务txid。
t_max:删除或更新此元组的事务txid,如果为删除或更新则为0。
t_cid:command id,在当前事务中,已经执行过多少条sql,例如执行第一条sql时cid=0,第二条cid=2。
t_ctid:保存着执行自身或者新元组的元组标识符(tid),在更新元组后tid指向新版本的元组,否则指向自己,这个我们后面会细细讨论。
介绍完上面的基本概念后我们再来看看postgresql如何通过b树索引找到对应的数据行的。

我们知道索引元组中是kv的结构,key代表的是查询条件的值,value即TID,TID中记录了两部分信息,block=2代表页面号,数据位于第几个块(页面),offset=2代表第二个元组,这样就通过索引直接定位了某一条记录,而不需要对页面进行扫描。
下面我们进入正题,我们再来看看元组是如何更新的,我们知道元组的更新其实是新插入一条记录如下图所示,如果没有hot技术的话,每更新一个行,就会插入一个元组,同时会在索引页中新增一一条元组,该元组中的tid指向新的元组,而索引的维护开销也是非常大的,可以想象,这样的话在频繁更新的系统中不仅数据会膨胀而且索引也会膨胀,同时维护索引的开销太大。

于是postgresql使用HOT(堆内元组技术)解决这个问题,总体思想是在更新时通过修改指针指向定位新元组,而不需要插入相应的索引元组。我们来看看hot更新的流程:
在元组结构的t_informask2字段中有两个标记位,heap_hot_update和heap_only_tuple,在更新tuple1时,postgresql会将tuple1(老元组)的标记位置为heap_hot_update,同时将tuple2(新元组)的标记位置为heap_only_tuple。


1.首先找到目标数据的索引元组
2.然后通过索引元组中的位置,访问行指针数组,找到行指针1
3.读取tuple1
4.发现tuple1的标记位是heap_hot_update,于是通过tuple1的t_ctid字段读取tuple2(上面也提到过,当元组被更新过后,元组的t_ctid字段指向新的元组)
上面的过程其实访问了tuple1和tuple2两个数据块,这时我们可能会考虑到一个问题,如果tuple1因为vacuum清理掉了,就无法通过tuple的ctid字段定位到tuple2了,为了解决这个问题,postgresql会在合适的时候进行行指针的重定向(redirect),这个过程称为修剪。

此时访问新元组的流程如下:
1.首先找到目标数据的索引元组
2.然后通过索引元组中的位置,访问行指针数组,找到行指针1
3.通过行指针的重定向,找到行指针2
4.通过行指针2定位tuple2
在postgresql进行修剪时,会挑选合适的时机来清理死元组,这个过程称为碎片整理,如下图所示:

碎片整理并不会清理索引元组,所以碎片整理比普通vacuum清理的开销要小的多。HOT特性降低了表和索引的空间消耗,同时减少了vacuum需要处理的元组数量,对于性能有很好的提升。
当然HOT技术也不是万能的,它也有不适用的场景,比如下面两个场景:
1.当更新的元组和老元组不在同一个page中时,指向该元组的索引元组也会被添加到索引页面中。
2.当索引的key值更新时,会在索引页面中插入一条新的索引元组。
学习精益求精,技术永无止境,加油吧。

http://huaguang.jxtcbmw.cn/twgx/ http://yz.cqtcxxw.cn/hgqza/ http://tuiguang.hntcxxw.cn/huizhou/ http://gx.lztcxxw.cn/twms/ http://jingren.hftcbmw.cn/shantou/ https://runan.tiancebbs.cn/ https://fenlei.tiancebbs.cn/sxxz/ https://beichuan.tiancebbs.cn/ http://shengshun.njtcbmw.cn/shuozhou/ http://taiying.njtcbmw.cn/wenchang/ https://henghezhen.tiancebbs.cn/ http://ouyu.hftcbmw.cn/gslx/ http://nalei.zjtcbmw.cn/ntx/ https://cqfengshan.tiancebbs.cn/ http://fs.shtcxxw.cn/shiyan/ http://jinqiang.ahtcbmw.cn/hntc/ http://ouyu.hftcbmw.cn/kj/
职业病防治计划和实施方案:https://www.nanss.com/gongzuo/18640.html 冬天开什么花:https://www.nanss.com/wenti/19460.html 政工师工作总结:https://www.nanss.com/gongzuo/18827.html 调查取证申请书:https://www.nanss.com/gongzuo/18460.html 地球是什么星:https://www.nanss.com/shenghuo/18366.html 一公里等于几千米:https://www.nanss.com/shenghuo/19019.html 幼儿园突发事件应急预案:https://www.nanss.com/gongzuo/19259.html 数学教学总结:https://www.nanss.com/gongzuo/19182.html 茶文化论文:https://www.nanss.com/xuexi/18812.html 母亲节的来历和意义:https://www.nanss.com/shenghuo/18973.html 林浩的故事:https://www.nanss.com/xuexi/19061.html 小学教师入党申请书:https://www.nanss.com/gongzuo/19922.html 院系推荐意见:https://www.nanss.com/gongzuo/18642.html 红旗谱读后感:https://www.nanss.com/xuexi/19585.html 石油是混合物吗:https://www.nanss.com/xuexi/18946.html oz是什么单位:https://www.nanss.com/wenti/19804.html 世界上最长的运河是哪一条:https://www.nanss.com/wenti/18374.html 月亮从哪边升起哪边落下:https://www.nanss.com/shenghuo/18208.html 考研时间:https://www.nanss.com/xuexi/20143.html 一尺八等于多少厘米:https://www.nanss.com/wenti/18980.html 关于学习的名言名句:https://www.nanss.com/yulu/19311.html 粘米粉是什么:https://www.nanss.com/yinshi/18537.html 我最喜欢的历史人物:https://www.nanss.com/xuexi/19292.html 工作汇报开头:https://www.nanss.com/gongzuo/18639.html 大学习大讨论心得体会:https://www.nanss.com/gongzuo/19604.html 点艾条熏房间的好处:https://www.nanss.com/shenghuo/19485.html 两栖动物有哪些:https://www.nanss.com/shenghuo/18345.html 床笠是什么:https://www.nanss.com/jiaju/18174.html 古代文学常识:https://www.nanss.com/xuexi/18614.html 刺梨的功效与作用:https://www.nanss.com/yinshi/19739.html