前言
postgresql 使用缓存来作为与磁盘读写的中间层,但是缓存的大小是有限的,当缓存不够用时需要剔除一些不常用的。但是如何高效的选出那些需要剔除的缓存呢,postgresql 针对不同的应用场景,提供了简单高效的不同算法。
替换算法
postgresql 主要提供了两种替换算法,ring 算法和 clock sweep 算法,分别针对批量读写和正常读写。
ring 算法
ring算法适合那些批量读写的场景,因为操作数据都是一次性的,这些数据在使用后就没有作用了。如果频繁的触发缓存替换,对性能造成没必要的损耗的。所以使用一个特定大小的环,循环使用。这种算法性能高,而且对缓存造成很大的影响。
ring算法的原理很简单,它有一个环状数组,数组的每个元素都对应一个buffer,注意到buffer的分配是动态的,也就是说开始的时候,数组的元素都为空。
每次需要获取替换的缓存,它都会从上次遍历的位置开始,直接返回下一个元素。如果这个数组元素没有分配buffer,则需要进行分配。当这个buffer被分配了,它会一直存在,不会被替换掉,除非被明确释放掉。
ring 算法的相关参数定义如下:
1
2
3
4
5
6
7
8
9
10
11typedef struct BufferAccessStrategyData
{
BufferAccessStrategyType btype; // 策略类型
intring_size; // 环大小
intcurrent; // 数组的遍历当前位置
boolcurrent_was_in_ring; // 数组当前位置的元素,有没有分配buffer
// 这里使用数组来表示环,当元素的值为InvalidBuffer(也就是0),表示还分配buffer给这个元素
Bufferbuffers[FLEXIBLE_ARRAY_MEMBER];
} BufferAccessStrategyData;
上面的BufferAccessStrategyType定义了哪种策略,定义如下