1. 参考资料
参考了前辈们的总结
https://yq.aliyun.com/articles/62314
http://www.jianshu.com/p/7a8737250456
2. 安装配置
安装pg_pathman的rpm包
rpm -ivh pg_pathman96-1.3.1-1.rhel6.x86_64.rpm
修改postgresql.conf配置文件,将pg_pathman添加到预加载lib中(注)
su - postgres
vim /pgsql/data/postgresql.conf
...
shared_preload_libraries = 'pg_pathman,...'
重启PG使配置文件的修改生效
pg_ctl restart
创建extension
postgres=# create extension pg_pathman ;
CREATE EXTENSION
postgres=# \dx
List of installed extensions
Name | Version | Schema | Description
------------+---------+------------+------------------------------
pg_pathman | 1.3 | public | Partitioning tool
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(2 rows)
注意:pg_pathman必须由Postmaster进程初始化,所以一定要写在shared_preload_libraries参数中,否则在create extension时会报错
2. 创建分区表
目前pathman仅支持hash和range分区,像mysql的list分区可以用range代替,比如按照每月31天,分为31个list的情况,可以定义range的间隔为1,分区个数31
2.1 hash分区
oas_route=# select create_hash_partitions
('oa_epp_user'::regclass, --主表OID
'PART_CODE', --分区列名,必须有not null约束
10, --分区个数
false); --不立即迁移数据
create_hash_partitions
------------------------
10
(1 row)
2.2 range分区
oas_route=# select create_range_partitions
('oasc_b_trade_order_storage'::regclass, --主表OID
'day', --分区列名,必须有not null约束
1, --起始值
1, --间隔值
31, --分区个数
false); --不立即迁移数据
create_range_partitions
-------------------------
31
(1 row)
注意:
- 分区列必须有not null约束
- 分区个数必须能覆盖已有的所有记录
2.3 迁移数据到分区表
partition_table_concurrently函数不会发生阻塞
oas_route=# select partition_table_concurrently
('oa_epp_user'::regclass, --主表OID
10000, --一个事务批量迁移多少记录
1.0); --获得行锁失败时,休眠多久再次获取,重试60次退出任务
NOTICE: worker started, you can stop it with the following command: select public.stop_concurrent_part_task('oa_epp_user');
partition_table_concurrently
------------------------------
(1 row)
停止数据迁移任务
oas_route=#select stop_concurrent_part_task(relation REGCLASS);
查看后台的数据迁移任务
oas_route=#select * from pathman_concurrent_part_tasks;
userid | pid | dbid | relid | processed | status
--------+-----+------+-------+-----------+--------
(0 rows)
数据迁移完成之后,select only主表的话,应该已经没有数据了,所有的数据都在分区表中
oas_route=# select count(*) from only oasc_b_recharge_order_storage;
count
-------
0
(1 row)
数据迁移完成后,建议禁用主表,这样执行计划就不会出现主表了
oas_route=# select set_enable_parent('oasc_b_recharge_order_storage'::regclass,false);
set_enable_parent
-------------------
(1 row)
3. 管理分区
3.1 自动新增分区
目前仅支持range分区表,insert一条不在现有分区范围的数据,再查看主表的属性,发现新增了10个分区,分区规则和既有的分区规则一致
test_db=# insert into tb1 values(20000000,'c2_char','c3_varchar');
test_db=# \d+ tb1
Table "public.tb1"
Column | Type | Modifiers | Storage | Stats target | Description
--------+-----------------------+-----------+----------+--------------+-------------
c1 | integer | not null | plain | |
c2 | character(10) | | extended | |
c3 | character varying(10) | | extended | |
Indexes:
"tb1_pkey" PRIMARY KEY, btree (c1)
Child tables: tb1_1,
tb1_10,
tb1_11,
tb1_12,
tb1_13,
tb1_14,
tb1_15,
tb1_16,
tb1_17,
tb1_18,
tb1_19,
tb1_2,
tb1_20,
tb1_3,
tb1_4,
tb1_5,
tb1_6,
tb1_7,
tb1_8,
tb1_9
备注:不推荐这么使用,如果插入的数据跨度很大,那么会自动创建很多的分区出来
3.2 分裂范围分区
对于某个比较大的范围分区,可以使用函数将分区分为2个分区
split_range_partition(partition REGCLASS, -- 分区oid
split_value ANYELEMENT, -- 分裂值
partition_name TEXT DEFAULT NULL) -- 分裂后新增的分区表名
使用该方法,数据会自动迁移到另一个分区
3.3 合并范围分区
指定两个需要合并分区,必须为相邻分区
merge_range_partitions(partition1 REGCLASS, partition2 REGCLASS)
3.4 向后添加范围分区
在末尾追加分区,沿用之前分区的规则
append_range_partition(parent REGCLASS, -- 主表OID
partition_name TEXT DEFAULT NULL, -- 新增的分区表名, 默认不需要输入
tablespace TEXT DEFAULT NULL) -- 新增的分区表放到哪个表空间, 默认不需要输入
3.5 向前添加分区
在头部追加分区,函数用法和3.4节中的类似
prepend_range_partition(parent REGCLASS,
partition_name TEXT DEFAULT NULL,
tablespace TEXT DEFAULT NULL)
3.6 添加单独分区
需要确保,添加的该分区不会存在数据交叉
add_range_partition(relation REGCLASS, -- 主表OID
start_value ANYELEMENT, -- 起始值
end_value ANYELEMENT, -- 结束值
partition_name TEXT DEFAULT NULL, -- 分区名
tablespace TEXT DEFAULT NULL) -- 分区创建在哪个表空间下
3.7 删除分区
3.7.1 删除单个分区
drop_range_partition(partition TEXT, -- 分区名称
delete_data BOOLEAN DEFAULT TRUE) -- 是否删除分区数据,如果false,表示分区数据迁移到主表
3.7.2 删除所有分区
drop_partitions(parent REGCLASS,
delete_data BOOLEAN DEFAULT FALSE)
3.8 绑定已有的表到分区中
将已经存在的某张表绑定到某个分区表之中,需要确保表的结构是一致的,包括被drop掉的column
attach_range_partition(relation REGCLASS, -- 主表OID
partition REGCLASS, -- 分区表OID
start_value ANYELEMENT, -- 起始值
end_value ANYELEMENT) -- 结束值
3.9 解绑分区
解绑分区,只是删除继承关系和约束,数据保留
detach_range_partition(partition REGCLASS) -- 指定分区名,转换为普通表
4. 小结
pg_pathman提供了一套方便的创建和管理分区表的函数,解决了传统的通过表继承来实现分区表功能的繁琐