7.堆内元组和仅索引扫描
7.1对内元组
当使用 HOT(heap only tuple) 特性更新行时,如果被更新的元组存储在老元组所在的页面中,PostgreSQL就不会再插入相应的索引元组,而是分别设置新元组的HEAP_ONLY_TUPLE标记位与老元组的HEAP_HOT_UPDATED 标记位,两个标记位都保存在元组的 t_informask2 字段中。在修剪和碎片整理处理过程中,也会使用这两个标记位。
更新后,PostgreSQL会读取两条元组,分别是 Tuple_1 和 Tuple_2,如果Tuple_1被清理,就会出现问题。为此,PG在合适的时候进行指针重定向,这个过程被称为修剪。这个在任何时候都可能发生,如SELECT/UPDATE/INSERT/DELETE。在修剪过程中,会择机清理死元组。 死元组碎片整理不涉及索引元组的移除,所以碎片整理比常规的清理开销少的多。
HOT不可用的场景
- 1.当更新的元组在其他的页面时,即和老元组不在同一个数据页中时,指向该元组的索引元组也会被添加至索引页中
- 2.当索引的键更新时,会在索引页中插入一条新的索引元组
pg_stat_all_tables视图提供了每个表的统计信息视图,也可以参考这个扩展
7.2仅索引扫描
当SELECT 语句的所有目标列都在索引键中时,为了减少I/O代价,仅索引扫描(又叫仅索引访问)会直接使用索引中的键值。
因为索引没有堆元组信息,如t_xmin和t_xmax,所以也要访问表。为解决,PostgreSQL使用目标数据表对应的可见性映射表来解决此问题。如果某一页中存储所有的元组都是可见的,PostgreSQL就会使用索引元组,而不去访问索引元组指向的数据页去检查可见性,否则,PostgreSQL读取索引元组指向的数据元组并检查元组可见性,而这就跟原来设想的一样。

本节英文版