PostgreSQL 11 preview - 分区表用法及增强 - 增加HASH分区支持 (hash, range, list)

简介:

标签

PostgreSQL , hash , range , list , 分区表


背景

PostgreSQL 10开始内置分区表的功能,11对分区表进行了增强,包括:

1、增加HASH分区的支持,支持了RANGE, HASH, LIST三种分区。

https://www.postgresql.org/docs/devel/static/ddl-partitioning.html

2、支持分区表的INSERT ON CONFLICT

https://www.postgresql.org/docs/devel/static/sql-insert.html

3、支持分区表的全局索引管理

《PostgreSQL 11 preview - 新功能, 分区表全局索引管理》

4、支持分区表的并行分区JOIN

《PostgreSQL 11 preview - 分区表智能并行JOIN (已类似MPP架构,性能暴增)》

分区表定义例子

https://www.postgresql.org/docs/devel/static/sql-createtable.html

range 分区表

1、单列range

CREATE TABLE measurement (    
    logdate         date not null,    
    peaktemp        int,    
    unitsales       int    
) PARTITION BY RANGE (logdate);    
CREATE TABLE measurement_y2016m07    
    PARTITION OF measurement (    
    unitsales DEFAULT 0    
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');    

2、多列RANGE

CREATE TABLE measurement_year_month (    
    logdate         date not null,    
    peaktemp        int,    
    unitsales       int    
) PARTITION BY RANGE (EXTRACT(YEAR FROM logdate), EXTRACT(MONTH FROM logdate));    
CREATE TABLE measurement_ym_older    
    PARTITION OF measurement_year_month    
    FOR VALUES FROM (MINVALUE, MINVALUE) TO (2016, 11);    
    
CREATE TABLE measurement_ym_y2016m11    
    PARTITION OF measurement_year_month    
    FOR VALUES FROM (2016, 11) TO (2016, 12);    
    
CREATE TABLE measurement_ym_y2016m12    
    PARTITION OF measurement_year_month    
    FOR VALUES FROM (2016, 12) TO (2017, 01);    
    
CREATE TABLE measurement_ym_y2017m01    
    PARTITION OF measurement_year_month    
    FOR VALUES FROM (2017, 01) TO (2017, 02);    

list 分区表

CREATE TABLE cities (    
    city_id      bigserial not null,    
    name         text not null,    
    population   bigint    
) PARTITION BY LIST (left(lower(name), 1));    
CREATE TABLE cities_ab    
    PARTITION OF cities (    
    CONSTRAINT city_id_nonzero CHECK (city_id != 0)    
) FOR VALUES IN ('a', 'b');    

如果想定义多级分区,那么在创建分区表时,也使用partition by即可

CREATE TABLE cities_ab    
    PARTITION OF cities (    
    CONSTRAINT city_id_nonzero CHECK (city_id != 0)    
) FOR VALUES IN ('a', 'b') PARTITION BY RANGE (population);    
    
    
CREATE TABLE cities_ab_10000_to_100000    
    PARTITION OF cities_ab FOR VALUES FROM (10000) TO (100000);    

hash 分区表

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);    

默认分区

CREATE TABLE cities_partdef    
    PARTITION OF cities DEFAULT;    

小结

PostgreSQL的分区表非常灵活,

1、可以按单列或多列分区

2、可以按表达式分区

3、可以创建多级分区(不限级数)

多级分区定义例子

1、创建主表

create table t_range_list(id int, info text, crt_time timestamp) partition by list ( mod(hashtext(info), 4) );      

2、创建一级分区,主表

create table t_range_list_0 partition of t_range_list (id  , info , crt_time ) for values in (0) partition by range (crt_time);      
create table t_range_list_1 partition of t_range_list (id  , info , crt_time ) for values in (1) partition by range (crt_time);      
create table t_range_list_2 partition of t_range_list (id  , info , crt_time ) for values in (2) partition by range (crt_time);      
create table t_range_list_3 partition of t_range_list (id  , info , crt_time ) for values in (3) partition by range (crt_time);      

3、创建2级分区表

create table t_range_list_0_201611 partition of t_range_list_0 (id  primary key, info , crt_time ) for values from ('2016-10-01') to ('2016-11-01');      
create table t_range_list_0_201612 partition of t_range_list_0 (id  primary key, info , crt_time ) for values from ('2016-11-01') to ('2016-12-01');      
      
create table t_range_list_1_201611 partition of t_range_list_1 (id  primary key, info , crt_time ) for values from ('2016-10-01') to ('2016-11-01');      
create table t_range_list_1_201612 partition of t_range_list_1 (id  primary key, info , crt_time ) for values from ('2016-11-01') to ('2016-12-01');      
      
create table t_range_list_2_201611 partition of t_range_list_2 (id  primary key, info , crt_time ) for values from ('2016-10-01') to ('2016-11-01');      
create table t_range_list_2_201612 partition of t_range_list_2 (id  primary key, info , crt_time ) for values from ('2016-11-01') to ('2016-12-01');      
      
create table t_range_list_3_201611 partition of t_range_list_3 (id  primary key, info , crt_time ) for values from ('2016-10-01') to ('2016-11-01');      
create table t_range_list_3_201612 partition of t_range_list_3 (id  primary key, info , crt_time ) for values from ('2016-11-01') to ('2016-12-01');      

绑定和解绑分区

1、绑定分区,指将已有的普通表,绑定到某个分区表下面,作为它的一个分区,绑定分区时,需要指定分区的区间。

ALTER TABLE [ IF EXISTS ] name    
    ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }    

2、解绑分区,指将某个分区从现有的分区表中摘除。

ALTER TABLE [ IF EXISTS ] name    
    DETACH PARTITION partition_name    

例如某个分区已经不怎么查到了,那么可以解绑,并使用DDL把它MOVE一个冷存储的表空间里面。(如果是阿里云RDS PG,那么可以MOVE到OSS里面)

绑定

1、将measurement_y2016m07普通表绑定到measurement。指定它的分区定义取值范围。

Attach a partition to range partitioned table:

ALTER TABLE measurement    
    ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');    

2、将cities_ab普通表绑定到cities。指定它的分区定义取值范围。

Attach a partition to list partitioned table:

ALTER TABLE cities    
    ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b');    

3、将cities_partdef普通表绑定到cities。并设置为默认分区。

Attach a default partition to a partitioned table:

ALTER TABLE cities    
    ATTACH PARTITION cities_partdef DEFAULT;    

3、将orders_p4普通表绑定到orders。指定它的分区定义取值范围。

Attach a partition to hash partitioned table:

ALTER TABLE orders    
    ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3);    

解绑

1、将分区measurement_y2015m12从measurement中摘除。

Detach a partition from partitioned table:

ALTER TABLE measurement    
    DETACH PARTITION measurement_y2015m12;    

分区表 insert on conflict 例子

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 (order_id primary key)     
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);    
    
CREATE TABLE orders_p2 PARTITION OF orders (order_id primary key)     
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);    
    
CREATE TABLE orders_p3 PARTITION OF orders (order_id primary key)     
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);    
    
CREATE TABLE orders_p4 PARTITION OF orders (order_id primary key)     
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);    
postgres=# insert into orders values (1,1,'test') on conflict (order_id) do nothing;    
    
ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification    

语法层面已支持分区表的insert on conflict,接下来就等提交分区表UK索引的PATCH。

https://commitfest.postgresql.org/16/1452/

分区表全局索引

《PostgreSQL 11 preview - 新功能, 分区表全局索引管理》

分区的优势

1、如果被访问的数据集中在某个分区内,那么使用分区的话,分区和索引都比元表更小,更容易加载到内存,提升性能。(虽然是BLOCK管理的,但是使用分区的情况下数据分布更紧凑,所以依旧是节约内存的)

2、当需要对整个分区进行更新时,操作单个分区,比操作单个大表更快(即使使用索引,也没有直接全表扫描分区快)。

3、维护数据更方便,例如需要删除某些分区的数据,可以直接DROP 分区,不需要DELETE。

4、加载数据也更方便,例如可以并行加载到不同的分区,速度比写入单表快,因为单表的话索引、BLOCK在大量数据导入时会产生一定的LOCK冲突,没有并行加载到各个分区快。

5、不经常访问的数据分区,可以移动到廉价存储。易于管理数据。

参考

https://www.postgresql.org/docs/devel/static/sql-createtable.html

https://www.postgresql.org/docs/devel/static/ddl-partitioning.html

《PostgreSQL 11 preview - 新功能, 分区表全局索引管理》

《PostgreSQL 11 preview - 分区表智能并行JOIN (已类似MPP架构,性能暴增)》

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

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

《PostgreSQL 传统 hash 分区方法和性能》

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

《PostgreSQL 10.0 preview 功能增强 - 内置分区表》

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

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
6月前
|
存储 关系型数据库 测试技术
拯救海量数据:PostgreSQL分区表性能优化实战手册(附压测对比)
本文深入解析PostgreSQL分区表的核心原理与优化策略,涵盖性能痛点、实战案例及压测对比。首先阐述分区表作为继承表+路由规则的逻辑封装,分析分区裁剪失效、全局索引膨胀和VACUUM堆积三大性能杀手,并通过电商订单表崩溃事件说明旧分区维护的重要性。接着提出四维设计法优化分区策略,包括时间范围分区黄金法则与自动化维护体系。同时对比局部索引与全局索引性能,展示后者在特定场景下的优势。进一步探讨并行查询优化、冷热数据分层存储及故障复盘,解决分区锁竞争问题。
816 2
|
9月前
|
机器学习/深度学习 文字识别 开发者
使用OCR库Pix2Text执行p2t.recognize()时出现list index out of range的错误信息(附有Pix2Text识别图片内容和laTex公式的代码)
有时候报错并不是你代码有问题,源码出错也是很常见的情况,比如之前使用mxgraph也出现了不知名bug,最后也是修改的源码解决的。有疑问欢迎交流~ 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
存储 分布式计算 NoSQL
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
大数据-40 Redis 类型集合 string list set sorted hash 指令列表 执行结果 附截图
157 3
|
SQL 监控 关系型数据库
PostgreSQL普通表转换成分区表
如何使用pg_rewrite扩展将普遍表转换成分区表
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。
|
关系型数据库 数据管理 Go
《PostgreSQL数据分区:原理与实战》
《PostgreSQL数据分区:原理与实战》
359 0
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
消息中间件 JSON NoSQL
Redis深度解析:核心数据类型之hash、list、set
Redis深度解析:核心数据类型之hash、list、set
|
存储 索引 Python
【Python】已解决:IndexError: list index out of range
【Python】已解决:IndexError: list index out of range
2572 1

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多