从tuple格式看PG设计之HOT
PG行记录格式


t_xmin 插入记录/元组 事务txid
t_xmax 删除/修改记录/元组 事务txid, 新插入t_xmax设置为0,
t_cid 事务内SQL执行顺序号,0开始
t_ctid 指向元组/新元组(block,offset) t_ctid
t_infomask2 HEAP_HOT_UPDATED(旧元组)HEAP_ONLY_TUPLE(无索引新元组)标志位
t_infomask 事务标准位,提交,撤销,进行中,子事务进行中
t_hoff 用户数据的偏移量
NULL bitmap null值位图
User data 实际的数据
从PG的tuple存储我们可以知道:更新操作并不是原地操作,而是update 旧记录t_xmax+ insert 新记录,如果没有针对的处理,那么索引指向tuple的位置就变化了,需要更新索引。对于更新的记录(update/delete)旧记录成为了死元组,做页面清理时需要移除,索引也对应需要更新。按照我们实际使用情况: 设计优良的库,一个表控制在3~5个索引,未考量的库恐怕一个表多达数几十个索引,即一次更新数据带来几次到几十次索引同时更新,IO开销巨大。
HOT基于索引开销的优化也就应运而生,HOT 即”Heap Only Tuple 仅元组堆“的缩写。可怎么实现呢:1.可以通过旧元组的t_ctid指向新元组t_ctid 链式访问。 2.修改索引指向的原始行指针。而通过t_ctid 链式访问会遇到2个问题:难免需要读取多行记录知道定位新记录位置,这样带来处理一个page下多行的cpu_tuple_cost开销;当vacuum清理后,dead tuple 删除,t_ctid链条断了.基于这些考虑,HOT步骤一般分成3步。
HOT步骤
a.行更新
旧tuple t_ctid 指向新tuple t_ctid , t_infomask2标记 HEAP_HOT_UPDATED,
新tuple t_infomask2标记HEAP_ONLY_TUPLLE
index item->lp1->tuple1(t_ctid)->tuple2(t_ctid)->tuple3(t_ctid)……->tuplen(t_ctid)
b.修剪
行指针pruning , 旧lp标记 Redirect 新lp
lp1(redirect) -> lpn ->tuplen
c.碎片整理
dead tuple defragmentation




