PostgreSQL数据库 OLTP高并发请求性能优化

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: 在多核系统中,一般TPS会随并发数的增加而提升,但是当并发数超过一定的数值(如CPU核数的2到3倍以后),性能开始下降,并发数越高,下降越严重。
在多核系统中,一般TPS会随并发数的增加而提升,但是当并发数超过一定的数值(如CPU核数的2到3倍以后),性能开始下降,并发数越高,下降越严重。
例子:
更新500万记录表中的1条随机记录。开8000个并发。
 
  

create table test_8000 (id int primary key, cnt int default 0);
insert into test_8000 select generate_series(1,5000000);
vi t.sql
\setrandom id 1 5000000
update test_8000 set cnt=cnt+1 where id=:id;
update test_8000 set cnt=cnt+2 where id=:id;

每次加载80个并发,循环100次,一共加载8000个并发。
 
  

vi test.sh
#!/bin/bash
for ((i=0;i<100;i++))
do
sleep 1;
pgbench -M simple -n -r -f ./t.sql -c 80 -j 80 -T 100000 -U postgres &
done

开始
 
 

. ./test.sh

当连接数达到8000后,观察TPS,我们可以使用PG的统计信息表来计算QPS。
 
  

postgres=# select count(*) from pg_stat_activity;
 count 
-------
  8002
(1 row)
postgres=# select timestamptz '2015-10-08 17:01:24.203089+08' - timestamptz '2015-10-08 17:01:16.574076+08';
    ?column?     
-----------------
 00:00:07.629013
(1 row)
postgres=# select 43819090-43749480;
 ?column? 
----------
    69610
(1 row)
postgres=# select 69610/07.629013;
       ?column?        
-----------------------
 9124.3782124896103860
(1 row)

8000个并发的时候,更新TPS约9124。大部分时间可能浪费在CPU调度上了。

另一种场景,
如果有8000个并发是空闲连接,只有10个在执行更新,性能是这样的:
先制造8000个空闲连接:
 
  

vi test.sql
select pg_sleep(100000);
vi test.sh
#!/bin/bash
for ((i=0;i<100;i++))
do
sleep 1;
pgbench -M simple -n -r -f ./test.sql -c 80 -j 80 -T 100000 -U postgres &
done
. ./test.sh
postgres=# select count(*) from pg_stat_activity;
 count 
-------
  8002
(1 row)

然后开启10个连接执行更新操作。
 
  

pgbench -M prepared -n -r -f ./t.sql -P 1 -c 10 -j 10 -T 1000 -U postgres postgres
progress: 1.0 s, 29429.2 tps, lat 0.336 ms stddev 0.109
progress: 2.0 s, 28961.1 tps, lat 0.343 ms stddev 0.114
progress: 3.0 s, 30433.8 tps, lat 0.326 ms stddev 0.103
progress: 4.0 s, 29597.1 tps, lat 0.336 ms stddev 0.114
progress: 5.0 s, 28714.1 tps, lat 0.346 ms stddev 0.117
progress: 6.0 s, 28319.0 tps, lat 0.351 ms stddev 0.121
progress: 7.0 s, 28540.0 tps, lat 0.348 ms stddev 0.118
progress: 8.0 s, 29408.9 tps, lat 0.338 ms stddev 0.111
progress: 9.0 s, 29178.1 tps, lat 0.340 ms stddev 0.119
progress: 10.0 s, 29146.9 tps, lat 0.341 ms stddev 0.118
progress: 11.0 s, 27498.5 tps, lat 0.361 ms stddev 0.123

这种方法的性能约6万 qps。

优化思路:
排队处理用户请求。类似pgbouncer或Oracle的shared server机制,真实处理请求的进程数有限。

使用PostgreSQL的advisory函数可以模拟这种排队机制:
 
  

create or replace function upd(l int,v_id int) returns void as $$
declare
begin
  LOOP
    if pg_try_advisory_xact_lock(l) then  -- 只有获得这个应用级锁才执行更新,否则就等待。
      update test_8000 set cnt=cnt+1 where id=v_id;
      update test_8000 set cnt=cnt+2 where id=v_id;
      return;
    else
      perform pg_sleep(30*random());  --  随机等待时间
    end if;
  END LOOP;
end;
$$ language plpgsql strict;


增加一个随机变量l,用来表示应用所的号码,也就是说模拟10个同时在更新的操作,其他的都在等待。
这个是没有经过优化的排队机制,因为不是独立的进程处理用户请求,依旧是backend process在处理用户请求,依旧有8000个进程。
 
  

vi t.sql
\setrandom id 1 5000000
\setrandom l 1 10
select upd(:l, :id);
vi test.sh
#!/bin/bash
for ((i=0;i<100;i++))
do
sleep 1;
pgbench -M simple -n -r -f ./t.sql -c 80 -j 80 -T 100000 -U postgres &
done
. ./test.sh

测试结果比较理想,已经提升了1倍性能。
 
  

postgres=# select now(),n_tup_upd+n_tup_hot_upd from pg_stat_all_tables where relname='test_8000'; now | ?column? -------------------------------+----------- 2015-10-08 19:06:37.951332+08 | 221045069 (1 row)
postgres=# select now(),n_tup_upd+n_tup_hot_upd from pg_stat_all_tables where relname='test_8000'; now | ?column? ------------------------------+----------- 2015-10-08 19:07:46.46325+08 | 222879057 (1 row)
postgres=# select timestamptz '2015-10-08 19:07:46.46325+08' - timestamptz '2015-10-08 19:06:37.951332+08'; ?column? ----------------- 00:01:08.511918 (1 row)
postgres=# select 222879057-221045069; ?column? ---------- 1833988 (1 row)
postgres=# select 1833988/68.5; ?column? -------------------- 26773.547445255474 (1 row)

模拟结果,相比不排队,有1倍以上的性能提升。  
TOP
 
  

top - 19:09:37 up 119 days,  3:59,  2 users,  load average: 0.96, 0.98, 1.01
Tasks: 8872 total,   5 running, 8866 sleeping,   1 stopped,   0 zombie
Cpu(s):  5.3%us,  0.8%sy,  0.0%ni, 93.9%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  132124976k total, 118066688k used, 14058288k free,   316752k buffers
Swap:  2097144k total,      148k used,  2096996k free, 63702028k cached


advisory lock是PG提供的一种轻量级的面向用户的锁(当然比LWLOCK是要重的),我之前在秒杀场景的优化中也有叙述,可以达到每秒处理19万次的单条记录更新请求的性能,并且保持1毫秒以内的RT。请参考。

把这种优化思路加入到PostgreSQL的内核中是比较靠谱的,最终实现的效果会和Oracle的shared server非常类似。
阿里云PG内核组的小鲜肉和老腊肉们,优化开始搞起吧。
在没有优化前,还是使用pgbouncer这种连接池吧。
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
|
Cloud Native OLAP OLTP
在业务处理分析一体化的背景下,开发者如何平衡OLTP和OLAP数据库的技术需求与选型?
在业务处理分析一体化的背景下,开发者如何平衡OLTP和OLAP数据库的技术需求与选型?
132 4
|
2月前
|
关系型数据库 分布式数据库 数据库
PolarDB PostgreSQL版:Oracle兼容的高性能数据库
PolarDB PostgreSQL版是一款高性能的数据库,具有与Oracle兼容的特性。它采用了分布式架构,可以轻松处理大量的数据,同时还支持多种数据类型和函数,具有高可用性和可扩展性。它还提供了丰富的管理工具和性能优化功能,为企业提供了可靠的数据存储和处理解决方案。PolarDB PostgreSQL版在数据库领域具有很高的竞争力,可以满足各种企业的需求。
|
6天前
|
关系型数据库 Java 数据库
docker部署postgresql数据库和整合springboot连接数据源
docker部署postgresql数据库和整合springboot连接数据源
16 0
|
8天前
|
SQL JSON 关系型数据库
[UE虚幻引擎插件DTPostgreSQL] PostgreSQL Connector 使用蓝图连接操作 PostgreSQL 数据库说明
本插件主要是支持在UE蓝图中连接和操作PostgreSQL 数据库。
16 2
|
14天前
|
分布式计算 DataWorks 关系型数据库
DataWorks产品使用合集之在使用 DataWorks 数据集成同步 PostgreSQL 数据库中的 Geometry 类型数据如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
24 0
|
15天前
|
分布式计算 关系型数据库 大数据
MaxCompute产品使用合集之怎么才可以将 PostgreSQL 中的 geometry 空间类型字段同步到 MaxCompute 或另一个 PostgreSQL 数据库
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
15天前
|
关系型数据库 MySQL 测试技术
【专栏】PostgreSQL数据库向MySQL迁移的过程、挑战及策略
【4月更文挑战第29天】本文探讨了PostgreSQL数据库向MySQL迁移的过程、挑战及策略。迁移步骤包括评估规划、数据导出与转换、创建MySQL数据库、数据导入。挑战包括数据类型不匹配、函数和语法差异、数据完整性和性能问题。应对策略涉及数据类型映射、代码调整、数据校验和性能优化。迁移后需进行数据验证、性能测试和业务验证,确保顺利过渡。在数字化时代,掌握数据库迁移技能对技术人员至关重要。
|
16天前
|
存储 关系型数据库 MySQL
【专栏】在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个
【4月更文挑战第27天】MySQL与PostgreSQL是两大主流开源数据库,各有特色。MySQL注重简单、便捷和高效,适合读操作密集场景,而PostgreSQL强调灵活、强大和兼容,擅长并发写入与复杂查询。MySQL支持多种存储引擎和查询缓存,PostgreSQL则具备扩展性、强事务支持和高可用特性。选择时应考虑项目需求、团队技能和预期收益。
|
20天前
|
SQL 关系型数据库 API
从API获取数据并将其插入到PostgreSQL数据库:步骤解析
使用Python处理从API获取的数据并插入到PostgreSQL数据库:安装`psycopg2`,建立数据库连接,确保DataFrame与表结构匹配,然后使用`to_sql`方法将数据插入到已存在的表中。注意数据准备、权限设置、性能优化和安全处理。
|
25天前
|
SQL Oracle 关系型数据库
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)