PostgreSQL pgbench tpcb 海量数据库测试 - 分区表测试优化

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 标签PostgreSQL , pgbench , tpcb背景pgbench是PG的一款测试工具,内置的测试CASE为tpcb测试。同时支持用户自己写测试CASE。大量自定义CASE参考https://github.com/digoal/blog/blob/master/201711/readme.md当我们使用tpcb测试CASE时,如果生成的数据量过于庞大,例如我最近在生成1万亿的CASE,可以考虑使用分区表,但是目前PG内置分区表的性能在分区非常多时,使用PREPARED STATEMENT会导致性能下降。

标签

PostgreSQL , pgbench , tpcb


背景

pgbench是PG的一款测试工具,内置的测试CASE为tpcb测试。同时支持用户自己写测试CASE。

大量自定义CASE参考

https://github.com/digoal/blog/blob/master/201711/readme.md

当我们使用tpcb测试CASE时,如果生成的数据量过于庞大,例如我最近在生成1万亿的CASE,可以考虑使用分区表,但是目前PG内置分区表的性能在分区非常多时,使用PREPARED STATEMENT会导致性能下降。

《PostgreSQL 查询涉及分区表过多导致的性能问题 - 性能诊断与优化(大量BIND, spin lock, SLEEP进程)》

建议使用pg_pathman分区插件,消除这个性能问题。

或者可以把pgbench的SQL改一下,使用udf,动态SQL来实现,性能依旧杠杠的。

pgbench tpcb 分区表 UDF动态SQL实现

1、原生QUERY如下

读写case

\set aid random(1, 100000 * :scale)  
\set bid random(1, 1 * :scale)  
\set tid random(1, 10 * :scale)  
\set delta random(-5000, 5000)  
BEGIN;  
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;  
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;  
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;  
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;  
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);  
END;  

只读case

\set aid random(1, 100000 * :scale)  
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;  

tpcb pgbench_accounts 分区表重构

1、定义结构

例如1万亿

pgbench -i -I dt --tablespace=tbs1 -s 10000000  

2、使用分区

create table p (like pgbench_accounts) partition by RANGE ( aid ) tablespace tbs1;  

3、创建4097个分区,每个分区244140625条记录

do language plpgsql $$                                                           
declare  
  i_rows_perpartition int8 := 244140625;  
begin  
  for i in 0..4096 loop  
    execute format ('create table pgbench_accounts%s partition of p for values from (%s) to (%s) tablespace tbs1', i, i*i_rows_perpartition, (i+1)*i_rows_perpartition);  
  end loop;  
end;  
$$;  

4、重命名表

drop table pgbench_accounts;  
  
alter table p rename to pgbench_accounts;  
  
-- alter table pgbench_accounts add constraint pk_pgbench_accounts_aid primary key (aid) using index tablespace tbs2;  

5、新建任务表,并行加载数据

drop table task;  
create table task(id int primary key);  
insert into task select i from generate_series(0,4095) t(i);  

6、新建基础数据表,写入244140625条数据。

create table init_accounts(aid int8);  
insert into init_accounts select generate_series(0,244140624);  

7、创建UDF,调用一次,往单个分区中写入244140625条数据.

create or replace function tpcb_init_accounts() returns void as $$  
declare  
  v_id int;  
begin  
  with tmp as (select * from task limit 1 for update skip locked),  
    tmp1 as (delete from task using tmp where task.id=tmp.id)  
    select id into v_id from tmp;  
    
  if found then  
    execute format ('insert into pgbench_accounts%s select aid+%s*244140625::int8, ((aid+%s*244140625::int8)-1)/100000 + 1, 0 from init_accounts on conflict do nothing', v_id, v_id, v_id);  
  end if;  
end;  
$$ language plpgsql strict;  

8、使用pgbench,开启64个并发,生成1万亿条tpcb pgbench_accounts测试数据。

vi test.sql  
select tpcb_init_accounts();  
  
nohup pgbench -M prepared -n -r -f ./test.sql -c 64 -j 64 -t 100 >./init.log 2>&1 &  

9、创建任务表,用于生成pgbench_accounts分区表PK

drop table task;  
create table task(id int primary key);  
insert into task select i from generate_series(0,4095) t(i);  

10、新建UDF,用于生成pgbench_accounts分区表PK

create or replace function tpcb_init_accounts_pkey() returns void as $$  
declare  
  v_id int;  
begin  
  with tmp as (select * from task limit 1 for update skip locked),  
    tmp1 as (delete from task using tmp where task.id=tmp.id)  
    select id into v_id from tmp;  
    
  if found then  
    execute format ('analyze pgbench_accounts%s', v_id);  
    execute format ('alter table pgbench_accounts%s add constraint pk_pgbench_accounts%s_aid primary key (aid) using index tablespace tbs2', v_id, v_id);  
  end if;  
end;  
$$ language plpgsql strict;  

11、生成pgbench_accounts分区表PK

vi test.sql  
select tpcb_init_accounts_pkey();  
  
nohup pgbench -M prepared -n -r -f ./test.sql -c 64 -j 64 -t 100 >./init.log 2>&1 &  

如果使用的是pg_pathman插件,不用这么麻烦。

1、使用pgbench生成结构

pgbench -i -I dt --tablespace=tbs1 -s 10000000  

2、转换为分区表

https://github.com/postgrespro/pg_pathman

《PostgreSQL 9.5+ 高效分区表实现 - pg_pathman》

3、使用pgbench生成数据

pgbench -i -I g -n --tablespace=tbs1 -s 10000000  

4、新增PK

表级parallel  
  
analyze 表  
  
pgbench -i -I p -n -s 10000000 --index-tablespace=tbs2  

tpcb UDF

1、读写

create or replace function tpcb_rw(     
  i_aid int8,     
  i_bid int4,     
  i_tid int4,     
  i_delta int4,     
  i_rows_perpartition int8     
) returns int as $$    
declare    
  i_suffix int := i_aid/i_rows_perpartition;     
  res int;     
begin    
  execute format('execute p1_%s(%s,%s)', i_suffix, i_delta, i_aid);    
  execute format('execute p2_%s(%s)', i_suffix, i_aid) into res;    
  UPDATE pgbench_tellers SET tbalance = tbalance + i_delta WHERE tid = i_tid;    
  UPDATE pgbench_branches SET bbalance = bbalance + i_delta WHERE bid = i_bid;    
  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (i_tid, i_bid, i_aid, i_delta, CURRENT_TIMESTAMP);    
  return res;    
exception when others then    
  execute format('prepare p1_%s(int,int8) as UPDATE pgbench_accounts%s SET abalance = abalance + $1 WHERE aid = $2', i_suffix, i_suffix);    
  execute format('prepare p2_%s(int8) as SELECT abalance FROM pgbench_accounts%s WHERE aid = $1', i_suffix, i_suffix);    
  execute format('execute p1_%s(%s,%s)', i_suffix, i_delta, i_aid);    
  execute format('execute p2_%s(%s)', i_suffix, i_aid) into res;    
  return res;    
end;    
$$ language plpgsql strict;     

2、只读

create or replace function tpcb_ro(     
  i_aid int8,     
  i_rows_perpartition int8     
) returns int as $$    
declare    
  i_suffix int := i_aid/i_rows_perpartition;    
  res int;    
begin    
  execute format('execute p2_%s(%s)', i_suffix, i_aid) into res;    
  return res;    
exception when others then    
  execute format('prepare p2_%s(int8) as SELECT abalance FROM pgbench_accounts%s WHERE aid = $1', i_suffix, i_suffix);    
  execute format('execute p2_%s(%s)', i_suffix, i_aid) into res;    
  return res;    
end;    
$$ language plpgsql strict;     

3、改成自定义脚本

读写CASE

vi rw.sql  
  
\set aid random(1, 100000 * :scale)  
\set bid random(1, 1 * :scale)  
\set tid random(1, 10 * :scale)  
\set delta random(-5000, 5000)  
SELECT tpcb_rw(:aid,:bid,:tid,:delta,244140625);  

只读case

vi ro.sql  
  
\set aid random(1, 100000 * :scale)  
SELECT tpcb_ro(:aid,244140625);  

参考

https://github.com/digoal/blog/blob/master/201711/readme.md

https://github.com/postgrespro/pg_pathman

《PostgreSQL 9.5+ 高效分区表实现 - pg_pathman》

《PostgreSQL Oracle 兼容性之 - DBMS_SQL(存储过程动态SQL中使用绑定变量-DB端prepare statement)》

https://www.postgresql.org/docs/devel/static/pgbench.html

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=60e612b602999e670f2d57a01e52799eaa903ca9

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
存储 NoSQL 关系型数据库
PostgreSQL列存扩展hydra简单测试
Hydra是一款PostgreSQL的扩展,为PostgreSQL增加了列存引擎,使得PostgreSQL的olap性能大幅提升,本文介绍Hydra基本的使用方法。
|
SQL 关系型数据库 测试技术
沉浸式学习PostgreSQL|PolarDB 20: 学习成为数据库大师级别的优化技能
在上一个实验《沉浸式学习PostgreSQL|PolarDB 19: 体验最流行的开源企业ERP软件 odoo》 中, 学习了如何部署odoo和polardb|pg. 由于ODOO是非常复杂的ERP软件, 对于关系数据库的挑战也非常大, 所以通过odoo业务可以更快速提升同学的数据库优化能力, 发现业务对数据库的使用问题(如索引、事务对锁的运用逻辑问题), 数据库的代码缺陷, 参数或环境配置问题, 系统瓶颈等.
944 1
|
3月前
|
监控 关系型数据库 数据库
PostgreSQL的索引优化策略?
【8月更文挑战第26天】PostgreSQL的索引优化策略?
97 1
|
2月前
|
缓存 关系型数据库 数据库
如何优化 PostgreSQL 数据库性能?
如何优化 PostgreSQL 数据库性能?
116 2
|
3月前
|
监控 关系型数据库 数据库
如何优化PostgreSQL的性能?
【8月更文挑战第4天】如何优化PostgreSQL的性能?
238 7
|
6月前
|
存储 JSON 关系型数据库
PostgreSQL Json应用场景介绍和Shared Detoast优化
PostgreSQL Json应用场景介绍和Shared Detoast优化
|
6月前
|
SQL 关系型数据库 OLAP
PostgreSQL从小白到高手教程 - 第46讲:poc-tpch测试
PostgreSQL从小白到高手教程 - 第46讲:poc-tpch测试
154 3
|
6月前
|
关系型数据库 OLAP OLTP
PostgreSQL从小白到高手教程 - 第45讲:poc-tpcc测试
CUUG PostgreSQL技术大讲堂系列公开课第45讲-POC-TPCC测试的内容,往期视频及文档,请联系CUUG。
154 1
|
6月前
|
弹性计算 关系型数据库 数据库
开源PostgreSQL在倚天ECS上的最佳优化实践
本文基于倚天ECS硬件平台,以自顶向下的方式从上层应用、到基础软件,再到底层芯片硬件,通过应用与芯片的硬件特性的亲和性分析,实现PostgreSQL与倚天芯片软硬协同的深度优化,充分使能倚天硬件性能,帮助开源PostgreSQL应用实现性能提升。
|
6月前
|
SQL 关系型数据库 PostgreSQL
PostgreSQL【部署 01】离线安装PostgreSQL+PostGIS踩坑及问题解决经验分享(含安装文件PostgreSQL+PostGIS及多个依赖+测试SQL)
PostgreSQL【部署 01】离线安装PostgreSQL+PostGIS踩坑及问题解决经验分享(含安装文件PostgreSQL+PostGIS及多个依赖+测试SQL)
683 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版