0

最近我开始对 PostgreSQL 空闲空间管理和碎片整理做一些研究。我知道堆上的每个页面都包含一个页眉、页面标识符、可用空间和项目。当插入一个新的元组时,一个新的项目标识符将被插入到空闲空间的开头,新的项目数据将被插入到空闲空间的末尾。

使用后Vacuum,dead tuples 的 item 标识和 item 数据将被移除。如果删除的项目标识符在其他标识符的中间,则标识符之间会有间隙。由于通常新的标识符将被添加到空闲空间的开头,这之间的空闲空间会再次被重用吗?如果是这样,我们怎样才能找到这个空间?

这是此场景的可视化示例:

真空后的页面

删除一些元组后,(0,3) 和 (0,5) 之间有未使用的空间。这个空间将如何再次被重用?谢谢!

4

3 回答 3

0

假设该表包含 2 页。我们看一下第一页(第 0 页)让我们假设插入了一些数据并且该页有三个元组(行)。现在如果假设我们删除了元组 2,那么 PG 会删除元组 2 并将剩余的元组重新排序以进行碎片整理,然后更新此页面的 FSM 和 VM。PostgreSQL 继续执行此过程直到最后一页(真空)。

当您进行真空吸尘时,不会删除不必要的行指针,它们将在将来被重用。

因为,如果删除行指针,则必须更新关联索引的所有索引元组。

于 2020-10-08T01:57:39.307 回答
0

您所谓的“项目标识符”的 PostgreSQL 技术术语是“行指针”。“项目指针”或“元组标识符”是页码和行指针((0,5)在您的图像中)的组合。

这种间接方式乍一看很尴尬,但好处是可以随时重新洗牌实际的元组数据以对可用空间进行碎片整理,而无需更改元组的地址。

行指针在页眉之后形成一个数组。当一个新的元组应该被添加到缓冲区时,可以使用任何空闲行指针。如果没有空闲行指针,则在数组末尾添加一个新行指针。供参考,请PageAddItemExtended参见src/backend/storage/page/bufpage.c

于 2020-10-08T02:22:38.523 回答
0

除非页面被截断并稍后重新添加,否则行指针数组永远不会被压缩。随着新元组的添加,未使用的数组槽将被重用。如果页面曾经充满了大量的小元组,然后删除并重新填充少量的大元组,则会有额外的未使用 lp 占用少量空间,永远不会被重用。

您可以使用 pageinspect 中的heap_page_itemswhere lp_off=0查找它们。

于 2020-10-08T14:05:32.663 回答