首页 » PostgreSQL/GaussDB » 聊聊PostgreSQL Visibility Map File?

聊聊PostgreSQL Visibility Map File?

在上一篇笔记中pg buffer中会记录除了数据外,还有XXXX_vm的Visibility Map, PostgreSQL 中的可见性映射在Vacuum期间起着至关重要的作用。它跟踪哪些表块仅包含可见元组,从而避免在vacuum操作期间扫描这些块。这显著优化了 I/O 操作,因为只处理可能包含死元组的块。同时对于Index only scan 时可见性映射文件也是决定是否需要回表的判断。

举例

[postgres@anbob 5]$ ls -l 16483*
-rw------- 1 postgres postgres 442368 Oct 17 21:01 16483
-rw------- 1 postgres postgres  24576 Oct 17 21:01 16483_fsm     
-rw------- 1 postgres postgres   8192 Oct 17 21:01 16483_vm

每个表 VM 由一个或多个 8 KB 页面组成,此文件以 ‘vm’ 后缀存储。

什么是Visibility Map

在 PostgreSQL 中,系统包含一种机制来监控表和索引中的页面,确定哪些页面仅包含所有正在进行的事务都可见的元组。每个表都有自己的可见性映射,该结构指示表文件中的各个页面是否完全干净或包含任何死元组。跟踪自上次vacuum以来哪些页面已被修改。

可见性映射为每个堆页面存储两位。第一位(如果已设置)表示此页面上的元组对所有会话都可见,或者换句话说,该页面不包含任何需要清理的元组。此信息可供index only scan 扫描使用(因为在pg中index没有独立的vm文件),在可以only index scan查询仅从索引文件取数据,并避免需要访问堆表中的元组来检查可见性。第二位(如果已设置)表示页面上的所有元组都已冻结。这意味着即使是wraparound  VACUUM 也不需要重新访问该页面。VM 可作为vacuum操作的快速参考,允许 PostgreSQL 跳过不需要清理的页面,从而提高清理效率。借助可见性映射,PostgreSQL 可以优化维护任务,减少管理数据库健康和性能所需的时间和资源。

假设该表由三页组成,第 0 页和第 2 页包含死元组,而第 1 页不包含。该表的 VM 保存了哪些页包含死元组的信息。在这种情况下,vacuum 处理会通过参考 VM 的信息跳过第 1 页。

源码 /postgres/blob/master/src/backend/access/heap/visibilitymap.c

 * IDENTIFICATION
 * src/backend/access/heap/visibilitymap.c
 *
 * INTERFACE ROUTINES
 * visibilitymap_clear - clear bits for one page in the visibility map
 * visibilitymap_pin - pin a map page for setting a bit
 * visibilitymap_pin_ok - check whether correct map page is already pinned
 * visibilitymap_set - set a bit in a previously pinned page
 * visibilitymap_get_status - get status of bits
 * visibilitymap_count - count number of bits set in visibility map
 * visibilitymap_prepare_truncate -
 * prepare for truncation of the visibility map

 

Visibility Map什么时候创建?

在新创建表时,可能不会立即看到对应的XXXX_vm文件,在表做autovacuum/vacuum时,会创建该文件。vm不存在也不会影响数据查询报错。

 

Visibility Map什么时候更新?

更新可见位是在Vacuum后;更新不可见位是在page上的任何一行数据在vacuum后第一次变动时,会立即清理该page对应的的可见性bit,表示该page已修改,即使Page上不再有任何数据.

当 VACUUM 意外重启或终止时会发生什么?

PostgreSQL 通过可见性映射跟踪包含死元组和未冻结元组的页面,以避免全表扫描。在 VACUUM 运行期间,此可见性映射会频繁更新,因此 VACUUM 操作的意外重启不需要再次处理这些页面。
在 wraparound vacuum的情况下,为了推进 relfrozenxid(以减少表年龄),VACUUM 必须在一次成功传递中扫描可见性映射中的所有页面。

仅insert 表是否需要 VACUUM?

是的,仅插入表需要vacuum,原因是冻结元组以避免事务回绕问题。更新可见性映射,这可以防止涉及index only scan 的查询回表,因为仅索引扫描需要检查可见性映射以查看堆数据页是否全部可见。

注意:索引只有单独的可用空间映射,没有可见性映射。

 

 

References

https://www.interdb.jp/pg/pgsql05/07.html

打赏

目前这篇文章还没有评论(Rss)

我要评论