分区表锁粒度差异 - pg_pathman VS native partition table

简介:

标签

PostgreSQL , 锁 , 粒度 , pg_pathman , 内置分区


背景

PostgreSQL 内置分区相比pg_pathman分区插件性能要差一大截:

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

主要原因:

1、与优化器有关,内置分区表,plan\bind时需要分析所有子表,所以子表越多,性能会越差。例如下面这个CASE就是分区过多引起的性能问题。

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

PPAS 10和pg_pathman插件都没有这个问题。

我们也可以通过这个profiling来对比 pg_pathman和内置分区的性能差异。

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

除了性能差异,实际上还有一个问题是锁的差异。

分区表锁粒度差异 - pg_pathman VS native partition table

观察锁

1、pg_pathman,仅锁目标分区。对非目标分区执行DDL,不需要等待。

create table tbl_range(id int not null, info text, crt_time timestamp);      
select create_range_partitions('tbl_range', 'id', 0, 100, 128);     
  
begin;  
insert into tbl_range values (1, 'test', now()) returning tableoid::regclass,*;  
  
  tableoid   | id | info |          crt_time            
-------------+----+------+----------------------------  
 tbl_range_1 |  1 | test | 2018-02-06 20:15:23.305754  
(1 row)  
  
INSERT 0 1  
postgres=# select relation::regclass,* from pg_locks ;  
  relation   |   locktype    | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction |  pid  |       mode       | granted | fastpath   
-------------+---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-------+------------------+---------+----------  
 pg_locks    | relation      |    20699 |    11577 |      |       |            |               |         |       |          | 4/18               | 41234 | AccessShareLock  | t       | t  
             | virtualxid    |          |          |      |       | 4/18       |               |         |       |          | 4/18               | 41234 | ExclusiveLock    | t       | t  
 tbl_range_1 | relation      |    20699 |    44464 |      |       |            |               |         |       |          | 3/8819             | 41174 | RowExclusiveLock | t       | t  
 tbl_range   | relation      |    20699 |    44456 |      |       |            |               |         |       |          | 3/8819             | 41174 | RowExclusiveLock | t       | t  
             | virtualxid    |          |          |      |       | 3/8819     |               |         |       |          | 3/8819             | 41174 | ExclusiveLock    | t       | t  
             | transactionid |          |          |      |       |            |     227217433 |         |       |          | 3/8819             | 41174 | ExclusiveLock    | t       | f  
(6 rows)  

2、native partition table,锁所有分区。导致对任意分区执行DDL都需要等待。

CREATE TABLE orders (      
    order_id     bigint not null,      
    cust_id      bigint not null,      
    status       text      
) PARTITION BY HASH (order_id);      
CREATE TABLE orders_p1 PARTITION OF orders      
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);      
CREATE TABLE orders_p2 PARTITION OF orders      
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);      
CREATE TABLE orders_p3 PARTITION OF orders      
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);      
CREATE TABLE orders_p4 PARTITION OF orders      
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);         
begin;  
insert into orders values (1, 1, 'test') returning tableoid::regclass,*;  
  
 tableoid  | order_id | cust_id | status   
-----------+----------+---------+--------  
 orders_p1 |        1 |       1 | test  
(1 row)  
  
INSERT 0 1  
postgres=# select relation::regclass,* from pg_locks ;  
    relation    |   locktype    | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction |  pid  |           mode           | granted | fastpath   
----------------+---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+-------+--------------------------+---------+----------  
 orders_p4      | relation      |    16461 | 75121104 |      |       |            |               |         |       |          | 3/57883            | 41256 | RowExclusiveLock         | t       | t  
 orders_p3      | relation      |    16461 | 75121098 |      |       |            |               |         |       |          | 3/57883            | 41256 | RowExclusiveLock         | t       | t  
 orders_p2      | relation      |    16461 | 75121092 |      |       |            |               |         |       |          | 3/57883            | 41256 | RowExclusiveLock         | t       | t  
 orders_p1      | relation      |    16461 | 75121086 |      |       |            |               |         |       |          | 3/57883            | 41256 | RowExclusiveLock         | t       | t  
 orders         | relation      |    16461 | 75121080 |      |       |            |               |         |       |          | 3/57883            | 41256 | AccessShareLock          | t       | t  
 orders         | relation      |    16461 | 75121080 |      |       |            |               |         |       |          | 3/57883            | 41256 | RowExclusiveLock         | t       | t  
                | virtualxid    |          |          |      |       | 3/57883    |               |         |       |          | 3/57883            | 41256 | ExclusiveLock            | t       | t  
 pg_locks       | relation      |    16461 |    11621 |      |       |            |               |         |       |          | 4/58165            | 41325 | AccessShareLock          | t       | t  
                | virtualxid    |          |          |      |       | 4/58165    |               |         |       |          | 4/58165            | 41325 | ExclusiveLock            | t       | t  

维护子表

在对主表有查询、插入时,维护子表,看看子表的反应。

insert into 主表 values (1,xxx);  -- 写入A子表  

1、TRUNCATE 非A子表

内置分区,锁冲突。

pg_pathman,无冲突。

2、detach 非A子表

内置分区,锁冲突。

pg_pathman,无冲突。

小结

内置分区表,只要操作主表,就需要对所有子表加锁(加相应的锁,例如sharedLock).

pg_pathman,仅仅对主表,以及被访问调度子表加锁。

因此,当我们需要使用DDL来维护子表时(例如truncate, attach, detach子表),使用pg_pathman不会与操作主表的SQL冲突,而使用内置分区的话,读主表由于锁所有子表,所以与子表DDL操作会发生冲突。需要特别注意。

参考

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

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

《PostgreSQL 商用版本EPAS(阿里云ppas) - 分区表性能优化 (堪比pg_pathman)》

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

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
编解码 监控 数据可视化
一文带你快速设计精美可视化大屏
可视化大屏👉数据可视化大屏是将一些业务的关键指标通过数据可视化的方式展示到一块或多块LED大屏上,以大屏为主要展示载体的数据可视化设计。数据可视化大屏可以用于信息展示、数据分析、监控预警等多种场景,帮助用户快速了解数据的价值和意义。可视化大屏的优点1️⃣操作灵活:数据可视化大屏可以支持智能化布局和组件的自由排版,可以根据不同的需求和场景进行个性化的设计和展示。2️⃣信息展示更加全面。
一文带你快速设计精美可视化大屏
|
数据库 UED Python
1、基于python多进程+pyqt5开发流畅界面程序
使用python+pyqt5开发界面程序,利用多进程分离界面和任务执行功能,达到界面流畅不卡顿的要求。 本文程序示例:https://github.com/AlvinsFish/UiExample
2719 0
1、基于python多进程+pyqt5开发流畅界面程序
|
人工智能 自然语言处理 算法
如何学习AIGC
【1月更文挑战第21天】如何学习AIGC
790 1
如何学习AIGC
|
存储 JavaScript 前端开发
在Flutter开发中,状态管理至关重要。随着应用复杂度的提升,有效管理状态成为挑战
在Flutter开发中,状态管理至关重要。随着应用复杂度的提升,有效管理状态成为挑战。本文介绍了几种常用的状态管理框架,如Provider和Redux,分析了它们的基本原理、优缺点及适用场景,并提供了选择框架的建议和使用实例,旨在帮助开发者提高开发效率和应用性能。
266 4
|
Go 索引
go语言按字符(Rune)遍历
go语言按字符(Rune)遍历
203 3
|
Linux
如何让linux显示器命令行界面不显示
若需在命令行界面快速关闭屏幕,可选方法包括:使用`setterm --blank force`立即关闭屏幕;利用`sudo vbetool dpms off`将显示器置于低功耗模式;在X server环境下执行`xset dpms force off`关闭屏幕;或是针对笔记本通过`echo 0 | sudo tee /sys/class/backlight/*/brightness`关闭背光。以上任一方法均可实现屏幕关闭,部分操作需要管理员权限,屏幕通常会在按键或移动鼠标后自动恢复。
1745 9
|
Linux 数据处理 开发者
深入解析Linux中的paste命令:数据处理与分析的得力助手
`paste`命令在Linux中是数据处理的利器,它按列拼接多个文件内容,支持自定义分隔符和从标准输入读取。例如,合并`file1.txt`和`file2.txt`,使用`paste file1.txt file2.txt`,默认以制表符分隔;若要使用逗号分隔,可运行`paste -d ',' file1.txt file2.txt`。当文件行数不同时,较短文件后会填充空白行。结合管道符与其他命令使用,如`cat file1.txt | paste -s`,可按行合并内容。注意文件大小可能影响性能。