PostgreSQL:给日志库整库月分区表扩分区

日志库分区表快到期了,接下来需要做较费力的扩分区工作,日志表分区格式一般有两种,一种是按日分区,一种是按月分区,按日分区的函数比较好写,这里不再介绍; 这里主要介绍给日志库所有月分区表扩分区的方法:

月分区表信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
db_log=> /dt+ log_event*
List of relations
Schema | Name | Type | Owner | Size | Description
---------------+--------------------------------+-------+---------------+------------+-------------
db_log | log_event| table | db_log | 8192 bytes |
db_log | log_event_201308 | table | db_log | 8192 bytes |
db_log | log_event_201309 | table | db_log | 8192 bytes |
db_log | log_event_201310 | table | db_log | 8192 bytes |
db_log | log_event_201311 | table | db_log | 8192 bytes |
db_log | log_event_201312 | table | db_log | 8192 bytes |
db_log | log_event_201401 | table | db_log | 8192 bytes |
db_log | log_event_201402 | table | db_log | 8192 bytes |
db_log | log_event_201403 | table | db_log | 8192 bytes |
db_log | log_event_201404 | table | db_log | 8192 bytes |
db_log | log_event_201405 | table | db_log | 8192 bytes |
db_log | log_event_201406 | table | db_log | 8192 bytes |
db_log | log_event_201407 | table | db_log | 8192 bytes |

备注:这里的分区表通过子表继承父表实现,并且不通过 trigger 形式实现,再来看一个 SQL。

查询库中所有分区表

查询库中所有分区表以及子表个数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
nspname ,
relname ,
COUNT(*) AS partition_num
FROM
pg_class c ,
pg_namespace n ,
pg_inherits i
WHERE
c.oid = i.inhparent
AND c.relnamespace = n.oid
AND c.relhassubclass
AND c.relkind = 'r'
GROUP BY 1,2 ORDER BY partition_num DESC;

在一个日志库上执行述查询,结果如下
PostgreSQL:给日志库整库月分区表扩分区

其中 partition_num 表示分区表个数,红色框框起来的表示是日分区表,分区数在 30 左右的为月分区表。这里仅截了一部分表,这个库的月分区表在 90 张左右,现在的目标是批量给这些月分区表扩分区。

整库月表扩分区函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
create or replace function fun_create_child_table_month(begin_date date, add_partition_num int4 ) returns integer as $$
declare
v_des_date date;
v_year char(4); --目标分区表年份
v_month char(2); --目标分区表月份
i_cnt int4;
table_rec record; --分区表父表结果集游标
date_rec record; --日期后辍结果集游标
v_partbl_name character varying(64); --父表名称
v_childtbl_name character varying(64); --子表名称
v_date_key character varying(32); --日期后辍

begin
--此函数功能:批量给整库月分区表扩分区,注意以下几点:
--1 分区表子表格式: tablename_yyyymm
--2 此函数仅支持月分区表,不支持列表分区,复合分区,取模分区等模式
--3 此函数所涉及的分区表不支付触发器形式的分区表,此函数适合在日志库中使用
--4 调用函数: select fun_create_child_table_month('2014-08-01',24); 表示从 2014-08-01 开始扩分区,给当前库所有月分区表扩 24 个分区
--5 由于新增子表的权限模块处理较复杂, 因此此函数仅新增分区表,不涉及权限处理。
--创建临时表并插入数据: 此表存储日期后辍标识

create temporary table if not exists tbl_month_suffix( id serial,date_key character varying (32));
FOR i_cnt IN 1 .. add_partition_num LOOP
i_cnt := i_cnt-1;
v_des_date := begin_date + i_cnt* interval '1 month';
v_year := split_part(split_part(v_des_date::text,' ',1),'-',1);
v_month :=split_part(split_part(v_des_date::text,' ',1),'-',2);
--RAISE NOTICE 'date: %,%', v_year,v_month;
execute 'insert into tbl_month_suffix (date_key) values (' || v_year || v_month || ')';
END LOOP;

--创建分区表
--以下列出可能是月分区表,也有可能是日分区表,筛选条件 < 100,比较粗暴,建议根据自己的环境调整此 SQL
FOR table_rec IN (SELECT
nspname ,
relname ,
COUNT(*) AS partition_num
FROM
pg_class c ,
pg_namespace n ,
pg_inherits i
WHERE
c.oid = i.inhparent
AND c.relnamespace = n.oid
AND c.relhassubclass
AND c.relkind = 'r'
GROUP BY 1,2 having count(*) < 100 ORDER BY partition_num DESC
) LOOP
v_partbl_name := table_rec.relname;
FOR date_rec in select date_key from tbl_month_suffix order by date_key LOOP
v_date_key := date_rec.date_key;
v_childtbl_name := v_partbl_name || '_' || v_date_key;
execute 'create table if not exists ' || v_childtbl_name || ' ( like ' || v_partbl_name || ' including all ) inherits (' || v_partbl_name || ')' ;
execute 'grant select on ' || v_childtbl_name || ' to dwetl';

END LOOP;
END LOOP;
RAISE NOTICE '分区表创建完成!';
return 1;
end;
$$ language 'plpgsql';

执行函数: 扩二年分区

给数据库中所有月分区表扩两年分区,执行函数:

1
db_log=>  select fun_create_child_table_month('2014-08-01',24);

备注:执行完后,查看下分区,看看是不是所有月分区表分区已从 201408 扩到 201607,扩完之后,接下来需要手工检查下新增表的权限,比如可能开通了查询帐号,这时权限需要手工处理,有兴趣的同学,也可以将权限模块加到函数中,做得更自动点。

总结

此扩分区脚本需要完善的地方很多,使用时建议根据实际情况修改。

参考

原创文章,作者:kirin,如若转载,请注明出处:https://blog.ytso.com/238044.html

(0)
上一篇 2022年1月30日
下一篇 2022年1月30日

相关推荐

发表回复

登录后才能评论