PG的FILL FACTOR参数优化

以前在Oracle数据库上,我们经常讨论PCTFREE参数,这个参数指定了一个新数据块在插入数据时,默认保留多大比例的空间,用于VARCHAR等可变长字段的UPDATE。实际上这个参数在Oracle的用户中也不太受到重视,在一般负载不是很大的系统中,这个参数设置与否对应用性能的影响不大,使用Oracle默认的10%已经足够了。不过在某些特殊高负载、高并发的交易型系统中,因为某个热表的PCTFREE设置过小导致的性能问题也是常见的,每年的优化项目中,我们都能够遇到一些这样的案例。一般情况下,将PCTFREE调大一些人,然后MOVE一下表,这个问题就基本上能解决了。

在PostgreSQL数据库中,也有一个类似的参数,称为FILLFACTOR,这个参数控制PG数据库中的新的数据块插入数据时的限制,当某个数据块的使用率超过这个值的时候,该数据块不再接受新数据的插入,剩余的空间也是被用于UPDATE等需要额外空间的操作。

PG数据库的FILLFACTOR 的默认值为 100 (%)。因此,元组通常无间隙地存储在页面中。 和Oracle数据库类似,PG的FILLFACTOR 也可以针对索引。默认的100%可以让一个页面存储更多的记录行数,有利于顺序扫描,而将FILLFACTOR降低的好处是提高了以页面为单位的离散访问,因为在页面中预留了可以保证 UPDATE 语句进行更新的空闲空间。在另一方面,如果FILLFACTOR参数设置的较低,相同记录的表需要存储到更多的页面中,会增加读写IO的成本。对于经常UPDATE 可变长字段的表或者索引,FILLFACTOR 的默认值100%明显是不合适的,设置一个较低的FILLFACTOR会确保系统长期运行时的性能稳定。

实际上设置不合理的FILLFACTOR导致的后果与设置不合理的PCTFREE参数是类似的,在PG数据库中,不合理的FILLFACTOR参数会导致相关表在buffer_content LWLOCK上产生更多的等待,从而影响高并发系统的性能。

创建表时要设置FILLFACTOR,应该写到表的WITH子句中,表创建后也可以使用ALTER TABLE命令去进行修改,不过和Oracle类似的是,对已经存在的表进行参数修改,只会影响修改后新建的数据块,老的数据块不会自动重组。下面是建表和修改表时采用非默认FILLLFACTOR的例子。

create table bmsql_order_line (

  ol_w_id         integer   not null,

  ol_d_id         integer   not null,

  ol_o_id         integer   not null,

  ol_number       integer   not null,

  ol_i_id         integer   not null,

  ol_delivery_d   timestamp,

  ol_amount       decimal(6,2),

  ol_supply_w_id  integer,

  ol_quantity     integer,

  ol_dist_info    char(24)

)  WITH (FILLFACTOR = 60);

ALTER TABLE bmsql_order_line SET (FILLFACTOR = 30);

下面我们通过一个实际的例子来验证一下这个参数,我们选取的是benchmark测试的场景,实际上我们的测试环境使用的是傲腾SSD盘,因此IO性能十分出色,这种硬件场景下,FILLFACTOR的影响会被缩小。另外benchmark测试场景优化的也比较好,FILLFACTOR的影响因素也不是太大。虽然如此,我们还是能从这两个测试场景中看出一些细微的差别。

首先我们使用默认的方式创建测试数据表,标准的benchmark测试建表脚本都是使用通用脚本的,因此FILLFACTOR都是使用默认值。从测试情况上看,在我们这个环境中,NewOrders的TPMC是267546,总的TPMC是594485。

通过perf命令采集的操作系统的2M事件上看,也没有发现特别严重的争用。

从等待事件采样上看,我们采用1秒采样一次,60次采样的汇总上看,里面产生了少量的buffer_content等待,我们还没有针对benchmark做相关的优化,因此目前的主要等待还在其他方面,比如lock_manager、transactionid两个等待占的比重最大,因此热快冲突还不算是本场景的最主要的问题。

接下来我们使用60%的FILLFACTOR再来做一次测试。

NewOrders的TPMC大概提高了4000,有一定的提高,不过提高并不大。

从同样采样频率和采样次数的等待事件分析上看,buffer_content等待只剩下1次了,比前面的19次少了不少,buffer_mapping的等待事件也消失了。这是因为FILLFACTOR调小之后,数据打散到更多的数据块中,数据块的争用减少了。

在实际应用场景中,对于存在少量热块冲突的热表和索引,降低FILLFACTOR参数的值可以有效的提升并发性能,如果热块冲突比较严重,那么使用HASH分区表会有更好的效果。不过如果某张表上经常还要做顺序扫描,那么采用HASH分区表可能会对顺序扫描产生较大影响,那么FILLFACTOR参数可能是一种折中的选择。具体采用何种策略,在实际应用中,还是需要综合权衡,选取一个能够两全其美的方案。

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值