PostgreSQL/可见性映射和空闲空间映射
每个表都存储在单独的磁盘文件中。这些文件的名称由数字组成,这些数字是系统目录中使用的表的内部对象标识符 (OID)。每个这样的文件都附带一个用于其可见性映射的文件和另一个用于其空闲空间映射的文件。它们具有相同的名称,扩展名为 '_vm' 和 '_fsm'。例如,这种三元组文件名的示例是:3083、3083_vm 和 3083_fsm。
这两个附加文件包含元信息,用于优化对原始文件的 I/O 活动,尤其是针对真空和冻结,但也用于其他写入活动。由于 I/O 按物理页面工作,元信息地址完整的物理页面,而不是像行或版本这样的页面任何部分。
可见性映射为原始文件的每个页面包含两个标志 - 存储为两个位。第一个位表示关联的页面只包含有效的行版本,即没有要真空的膨胀。第二个位表示页面只包含已冻结的行版本。
请考虑两个细节。首先,在大多数情况下,一个页面包含许多行或行版本。但是,这两个标志都与页面相关联,而不是与单个行或行版本相关联。只有当标志对页面上存储的所有行版本有效时,才会设置标志。其次,由于每个页面只有两位(两位对应于 8 千字节,大约是 1:32.000 的关系),可见性映射比原始文件小得多。
VACUUM 和自动真空设置标志。对页面上任何行版本的任何写入操作都会清除标志。
可见性映射帮助 VACUUM 和自动真空节省不必要的 I/O。当第一个位被设置时,没有必要读取原始页面并检查其内容以删除膨胀。很明显没有膨胀。相应地,如果 VACUUM 或自动真空必须执行行的冻结,它们可以跳过第二个位表明页面只包含已冻结的行版本的页面 - 不需要冻结。
空闲空间映射跟踪每个页面的空闲未使用空间量。它被组织为一个高度压缩的 (rounded) 每个页面空闲空间大小的 B 树。
VACUUM 和自动真空根据其写入操作(将行版本标记为“已过时”并重新排列页面的物理布局)更改空闲空间映射。其他写入操作会查询空闲空间映射以找到具有足够空闲空间以进行预期写入操作的页面,并在之后更改空闲空间映射。