文档

表大小缓存

更新时间:

本文介绍了PolarDB PostgreSQL版的表大小缓存功能。

背景信息

在一条SQL被数据库执行的生命周期中,存在若干次对系统表和用户表及其索引的查询。在这个过程中,PolarDB PostgreSQL版会频繁通过存储管理层(Storage Manager, smgr)的smgrnblocks接口获取表文件的块数量。smgrnblocks最终通过文件系统的lseek接口获取文件长度,并根据块大小计算出块数量。由于smgrnblocks处于SQL处理的关键路径上,频繁调用文件系统接口会严重影响数据库的性能。对于使用分布式文件系统的PolarDB PostgreSQL版来说,调用PolarFS lseek的时延远高于单机文件系统的lseek,从而拖慢SQL的执行时间。

为了降低对文件系统的调用频率,PolarDB PostgreSQL版在存储管理层实现了对表文件块数量的缓存(Relation Size Cache, RSC),在共享内存中缓存表的块数量,并在表的块数量发生变化时更新共享内存中的缓存值。对表文件块数量的查询将优先使用缓存,从而降低对文件系统的请求次数,加快SQL的执行速度。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 15(内核小版本15.7.1.1及以上)。

  • PostgreSQL 14(内核小版本14.12.23.1及以上)。

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:

select version();

功能介绍

RSC查询

RSC由共享内存中的一维数组与哈希表组成:

  • 一维数组中的每一个缓存项都保存了一个Relation(表或索引)的块数量。

  • 哈希表记录了Relation的存储层唯一标识符RelFileNode与数组中缓存项的映射关系。

所有进程将通过依次通过以下两级索引来尝试查询RSC:

  • 第一级索引:缓存上一次访问的RSC缓存项的指针和版本号(generation)。如果本次访问的表与上次访问的表相同,且指针指向的RSC缓存项的版本号没有被修改过,那么进程可以直接通过指向缓存项的指针得到表的块数量。在对特定表的读多写少的场景中,第一级索引能够以较高的概率被命中。当RSC哈希表中的映射关系发生变化时,除了哈希表本身需要被修改,相对应的RSC缓存项版本号需要被自增,以便让RSC的第一级索引失效。

  • 第二级索引:当第一级索引失效时,通过查询共享内存中的哈希表可以得到当前表对应的RSC缓存项,得到表的块数量,并更新第一级索引。

如果通过上述两级索引都无法在RSC中查询到表和对应的块数量,将会触发RSC缓存淘汰,使用SLRU算法选择一个最近不怎么被使用的RSC缓存项清空。接下来会真正调用文件系统的lseek,并将得到的块数量更新到刚才清空的RSC缓存项中,并同步更新上述两级索引。

RSC更新(Primary/Standby节点)

开启RSC缓存功能后,涉及到表文件大小变更的存储管理层接口,需要同步更新共享内存中的RSC缓存项,确保缓存中表的块数量值与文件系统中的实际块数量一致。

  • 在表文件扩展(extend)页面的接口中,需要将扩展后的表文件块数量更新到RSC中。

  • 在表文件截断(truncate)的接口中,需要将截断后的表文件块数量更新到RSC中。

Standby节点由于采用物理复制与Primary节点同步,在回放WAL日志的过程中,同样会调用上述的存储管理层接口修改表的文件长度,故RSC缓存的更新方式与Primary节点无异。

RSC更新(Replica节点)

Replica节点与Primary节点共享物理存储,使用LogIndex机制与Primary节点同步。Replica节点不对存储做写操作,因此无法在存储管理层的接口中更新内存中的RSC缓存值。

Replica节点通过解析WAL日志中引用的数据块编号,与当前RSC缓存中的块数量值做比较,判断共享存储上的文件是否发生了长度变更。如果解析到WAL日志中的块编号已经超过了当前缓存的块数量,那么将RSC缓存中的值更新到被引用数据块所在的块数量。如果解析到表示文件发生了截断的WAL日志,那么直接丢弃RSC中缓存的块数量,等待下一次文件系统调用重新填充缓存。

使用指南

GUC参数

RSC提供如下GUC参数控制:

参数

描述

polar_enable_rel_size_cache

是否开启RSC功能,取值范围如下:

  • on(默认值):开启RSC功能。

  • off:关闭RSC功能。

polar_enable_replica_rel_size_cache

Replica节点是否开启RSC功能,取值范围如下:

  • on(默认值):Replica节点开启RSC功能。

  • offReplica节点关闭RSC功能。

polar_enable_standby_rel_size_cache

Standby节点是否开启RSC功能,取值范围如下:

  • on(默认值):Standby节点开启RSC功能。

  • offStandby节点关闭RSC功能。

性能测试

  • RSC关闭时,对32 GB表的块数量请求延时约为55 us:

    SHOW polar_enable_rel_size_cache;
     polar_enable_rel_size_cache
    -----------------------------
     off
    (1 row)
    
    SELECT polar_smgrperf_nblocks(32, true, false);
    NOTICE:  testing logical file length with 32 GB
    INFO:  iops=18341.1/s, lat=54.52us
    INFO:  iops=17504.0/s, lat=57.13us
    INFO:  iops=17960.8/s, lat=55.68us
    INFO:  iops=17973.0/s, lat=55.64us
    INFO:  iops=17603.5/s, lat=56.81us
    INFO:  iops=17403.8/s, lat=57.46us
    INFO:  iops=17506.2/s, lat=57.12us
    INFO:  iops=18061.7/s, lat=55.37us
  • RSC开启时,对32 GB表的块数量请求延时约为0.07 us:

    => SHOW polar_enable_rel_size_cache;
     polar_enable_rel_size_cache
    -----------------------------
     on
    (1 row)
    
    => SELECT polar_smgrperf_nblocks(32, true, false);
    NOTICE:  testing logical file length with 32 GB
    INFO:  iops=14155515.6/s, lat=0.07us
    INFO:  iops=13897273.6/s, lat=0.07us
    INFO:  iops=13869926.3/s, lat=0.07us
    INFO:  iops=13779602.7/s, lat=0.07us
    INFO:  iops=14159120.5/s, lat=0.07us
    INFO:  iops=14147065.6/s, lat=0.07us
    INFO:  iops=14124141.9/s, lat=0.07us
    INFO:  iops=14162773.3/s, lat=0.07us