PostgreSql建表属性fillfactor的设定对表性能的提升

--2018/10/15
select * from sor.test1_10_03
--测试fillfactor对表效能的影响
--
--创建测试表
--    test1设置fillfactor=100
--    test2设置fillfactor=80
--    drop table if exists  test1;
--    drop table if exists  test1_10_03;
create table test1_10_03(
    objectid bigserial not null,                --唯一编号,主键
    name text not null,                         --名称
    describe text,                              --备注
    generate timestamptz default now() not null,--创建日期
    constraint pk_test1_objectid primary key(objectid)
)with (fillfactor=100);
--2018/10/19  注意建表的时候的主键约束会自动创建唯一索引,索引名为  tablename_pk,即test1_10_03_pkey
alter table test1_10_03 cluster on test1_10_03_pkey;

create table test2_10_03(
    objectid bigserial not null,                --唯一编号,主键
    name text not null,                         --名称
    describe text,                              --备注
    generate timestamptz default now() not null,--创建日期
    constraint pk_test1_objectid primary key(objectid)
)with (fillfactor=80);
alter table test2_10_03 cluster on test2_10_03_pkey;

---------------------------------------------------------------
/****************************************************************************************
    创建随机生成中文字符函数
drop function if exists gen_random_zh(int,int);
****************************************************************************************/
create or replace function gen_random_zh(int,int)
    returns text
as $$
    select string_agg(chr((random()*(20901-19968)+19968 )::integer) , '')  from generate_series(1,(random()*($2-$1)+$1)::integer);
$$ language sql;
/****************************************************************************************
    导入测试数据
****************************************************************************************/
insert into test1_10_03(name)
  select gen_random_zh(8,32) from generate_series(1,10000);
insert into test2_10_03(name)
    select gen_random_zh(8,32) from generate_series(1,10000);
/****************************************************************************************
    为保证执行计划准确,数据导入完成后执行vacuum
****************************************************************************************/
vacuum freeze VERBOSE analyze test1_10_03;
vacuum freeze VERBOSE analyze test2_10_03;

/*查看test1_10_03数据在页面种的布局*/

select ctid,objectid from test1_10_03 limit 500;
--test1_10_03 的fillfactor = 100,每个数据块(页)的数据量为300条左右
0,304
vacuum 后(0,290)
--test1_10_03 的fillfactor = 80,即300*0.8 = 240条。每个数据块(页)的数据量为240条左右
select ctid,objectid from test2_10_03 limit 500;
(0,237) vacuum后(0,237)

/*表膨胀测试*/
select ctid from test1_10_03 where objectid = 93
ctid = (0,15)
update test1_10_03 set name = gen_random_zh(8,32) where objectid = 93
ctid = (5,154)
--如果test1_10_03上有索引的话,更新的字段如果不是索引的键值时,由于新行的物理位置发生了变化,因此仍然需要更新索引,这会导致表的性能下降。
--为了解决这个问题,PG引入了一个Heap-Only tuples技术,使用HOT技术,新行和旧行在同一个数据块内,旧行会有一个指针,指向新行,这样就不需要更新索引了,当索引访问到数据行时,会根据这个指针找到新行。
--HOT技术的使用有一个前提,就是新行和旧行必须在同一个数据块。
select ctid from test2_10_03 where objectid = 93
ctid = (0,15)
update test2_10_03 set name = gen_random_zh(8,32) where objectid = 93
ctid = (0,241)
--通过设定fillfactor为80%代表的是往一个数据块插入的数据占用了该数据块的80%后旧不再往该数据块插入数据了,保留的20%空间就是为更新数据时使用。该比例可以根据实际业务对表的更新频率。
--利弊分析
--fillfator会影响插入数据的效率,但是delete和update的效能会提升。所以该参数的取值决定于实际的业务逻辑。

猜你喜欢

转载自blog.csdn.net/MyySophia/article/details/83313115