目录

一、前言

二、版本详情

二、创建分区表

三、新增分区

        3.1、新增分区

        3.2、批量新增分区

四、删除分区

        4.1、删除分区

        4.2、批量删除分区

五、查看分区表详情

六、其他

一、前言

        本文记录一些postgresql中分区表的一些操作,包括但不限于创建分区表、删除分区、新增分区、清除分区数据等。

二、版本详情

        postgresql version:6.13.0

        python version:2.7.13

二、创建分区表

-- 范围性创建分区示例
-- 指定创建分区表名称为t_partition_table 指定分区字段为data_bsn_dt
-- 并创建一个名称为p_20210701的分区,此分区数据范围为2021-07-01
create table tfdd.t_partition_table(
    id varchar(32)
    ,name varchar(32)
    ,data_bsn_dt date
)
with (appendonly=true, compresslevel=5)
distributed by (id)
partition by range(data_bsn_dt)
(
  partition p_20210701 start ('2021-07-01'::date) inclusive end ('2021-07-02'::date) exclusive every ('1 day'::interval)
);

三、新增分区

        对于一个分区表,我们后续可能会频繁需要新增分区来满足业务需要。所以在通常项目会使用shell脚本执行psql命令,并配合crontab定时执行,用以满足每日按天分区的业务需求(本文案例业务背景是这样的)。

        3.1、新增分区

-- 新增分区,分区名称为p_20210702
-- inclusive 包含 20210702
-- exclusive 不包含 20210703
alter table tfdd.t_partition_table add partition p_20210702 start ('2021-07-02') inclusive end ('2021-07-03') exclusive;

        3.2、批量新增分区

                假如项目刚上线,我们需要初始化近半年或近一年的数据,如果按照上面一个个复制修改sql又会很费时费力,这时我们可以使用循环来达到批量执行新增分区语句。

-- 定义一个循环语句
-- stdt、endt分别为按天创建分区的开始时间和结束时间
do $$
declare
  stdt date := '2021-07-02';  
  endt date := '2021-07-31';
  curr_date date := stdt;
begin
  while curr_date <= endt loop    -- 包含开始结束
    execute 'alter table tfdd.t_partition_table add partition p_' || to_char(curr_date,'YYYYMMDD') || ' start (date''' || to_char(curr_date,'YYYY-MM-DD') || ''') inclusive end (date ''' || to_char(curr_date + interval '1 day','YYYY-MM-DD') || ''') exclusive';
    curr_date := curr_date + interval '1 day';
  end loop;
end $$
;

四、删除分区

        当然,有增就有减。当项目上线到一段时间后,分区数量会累加变得很多,当业务上我们不再需要这么多的数据的时候,我们就可以把不需要的数据删除掉。

        4.1、删除分区

-- partition_name 为新增分区时指定的分区名称
alter table tfdd.t_partition_table drop partition partition_name;

        4.2、批量删除分区

                批量删除参考3.2节批量新增分区逻辑,换汤不换药。

-- 循环删除分区
do $$
declare
  stdt date := '2021-07-01';  
  endt date := '2023-11-30';
  curr_date date := stdt;
  p_date char(20);
begin
  while curr_date <= endt loop    -- 包含开始结束
    p_date := 'p_' || to_char(curr_date,'YYYYMMDD');
    execute 'alter table tfdd.t_partition_table drop partition ' || p_date;
	raise notice 'drop successful of %',p_date;
    curr_date := curr_date + interval '1 day';
  end loop;
end $$
;

        这里记录一个批量删除近n天分区的存储过程

-- 在schema下创建存储过程
-- 删除n天外的分区,简单理解为维护分区表中分区范围近n天。
create or replace function schema.drop_table_days(table_name character varying,table_number interval day)
returns void
language plpgsql
as $function$
	declare
	v_date char(20);
	partition_name varchar(64);
	begin
		for v_date in select substring(inhrelid::regclass::text from length(table_name)+10 for 8) from pg_inherits
			where inhparent::regclass::text=table_name
			and substring(inhrelid::regclass::text from length(table_name)+10 for 8)::date < current_date - table_number order by 1
			loop
				partition_name := 'p_' || v_date;
				raise notice '% will be droped partition!',partition_name;
				execute 'alter table ' || table_name || ' drop partition ' || partition_name;
				raise notice 'partition % have been droped successful!',partition_name;
		end loop;
	end;
$function$;


-- 调用存储过程
select drop_table_days('schema.table_name',interval '760 day')

五、查看分区表详情

-- 用于查找某个表的分区信息
select
	c.relname
from pg_class c
inner join pg_inherits i on i.inhrelid = c. oid
inner join pg_class d on d.oid = i.inhparent
where d.relname = 't_partition_table';


-- 返回如下
              relname
------------------------------------
 t_partition_table_1_prt_p_20210701
(1 row)

六、其他

        最后记录一些在linux后台使用postgresql的命令

-- 切换linux用户
su gpadmin

-- 启动postgresql服务
gpstart

-- 停止postgresql服务
gpstop

-- 进入postgresql数据库
psql/psql -u user

-- 切换数据库
\c xxx