一、原始表
/**表**/
CREATE TABLE "public"."test1" (
"id" int8 NOT NULL,
"name" varchar(255) COLLATE "pg_catalog"."default",
"created_time" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" int8,
"updated_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
"updated_by" int8,
"delete_flag" bool NOT NULL DEFAULT false,
CONSTRAINT "test1_pkey" PRIMARY KEY ("id")
)
;
ALTER TABLE "public"."test1"
OWNER TO "postgres";
/**数据**/
INSERT INTO "public"."test1"("id", "name", "created_time", "created_by", "updated_time", "updated_by", "delete_flag")
VALUES (20220801000, '20220801000', '2022-08-01 00:00:00', NULL, NULL, NULL, false);
INSERT INTO "public"."test1"("id", "name", "created_time", "created_by", "updated_time", "updated_by", "delete_flag")
VALUES (20220801001, '20220801001', '2022-08-01 00:00:01', NULL, NULL, NULL, false);
INSERT INTO "public"."test1"("id", "name", "created_time", "created_by", "updated_time", "updated_by", "delete_flag")
VALUES (20220901001, '20220901001', '2022-09-01 00:00:01', NULL, NULL, NULL, false);
INSERT INTO "public"."test1"("id", "name", "created_time", "created_by", "updated_time", "updated_by", "delete_flag")
VALUES (20221001001, '20221001001', '2022-10-01 00:00:01', NULL, NULL, NULL, false);
二、创建分区表
以 test1 表为例,创建分区表 test1_fenqu
CREATE TABLE "public"."test1_fenqu" (
"id" int8 NOT NULL,
"name" varchar(255) COLLATE "pg_catalog"."default",
"created_time" timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" int8,
"updated_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
"updated_by" int8,
"delete_flag" bool NOT NULL DEFAULT false,
CONSTRAINT "test1_fenqu_pkey" PRIMARY KEY ("id","created_time")
)
PARTITION BY RANGE (
"created_time" "pg_catalog"."timestamp_ops"
)
;
ALTER TABLE "public"."test1_fenqu"
OWNER TO "postgres";
三、导入分区脚本
1、“create_partition_fun_init”(“init_time” varchar)
CREATE OR REPLACE FUNCTION "public"."create_partition_fun_init"("init_time" varchar)
RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
start_time VARCHAR;
BEGIN
IF "init_time" is not null THEN
start_time ="init_time";
ELSE
start_time =TO_CHAR(now(), 'YYYY-MM-DD');
END IF;
--M:月 Q :季度 S:半年 Y:一年
EXECUTE 'select create_partition_fun('''||start_time ||''',''M'',''test1_fenqu'')';
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION "public"."create_partition_fun_init"("init_time" varchar) OWNER TO "postgres";
2、“create_partition_fun”(“init_time” varchar, “partition_type” varchar, “table_name” varchar)
CREATE OR REPLACE FUNCTION "public"."create_partition_fun"("init_time" varchar, "partition_type" varchar, "table_name" varchar)
RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
-- table_name VARCHAR ;//表名
-- partition_type VARCHAR:='M';M:月 Q :季度 S:半年 Y:一年
-- 月 从每月的第一天~下月的第一天 季度:当前时间所在的季度首月第一天~下季度的首月第一天 半年:当前年的1月第一天~当前年的七月第一天 或者+6 一年:就是全年一整年 第一年的第一天~第二年的第一天
now_schema VARCHAR := CURRENT_SCHEMA;
create_suffix VARCHAR;
from_date VARCHAR;
to_date VARCHAR;
table_exist_mark INTEGER;
start_time VARCHAR;
contion INTEGER;
create_index INTEGER;
m_mark INTEGER:=0;
BEGIN
IF "init_time" is not null THEN
start_time ="init_time";
ELSE
start_time =TO_CHAR(now(), 'YYYY-MM-DD');
END IF;
create_index = 1;
WHILE create_index >0 LOOP
EXECUTE ' select case when to_date('''||start_time||''', ''YYYY-MM-DD'')>=now() then 0 else 1 end' INTO contion;
IF contion = 0 THEN
create_index=0; --终止执行
ELSE
IF partition_type = 'M' THEN
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' month'', ''YYYYMM'')' INTO create_suffix;
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' month'', ''YYYY-MM'') || ''-01 00:00:00''' INTO from_date;
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||2||' month'', ''YYYY-MM'') || ''-01 00:00:00''' INTO to_date;
--计算下一个分区时间
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' month'', ''YYYY-MM-DD'') ' INTO start_time;
END IF;
IF partition_type = 'Q' THEN
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||3||' month''), ''YYYYMM'') ' INTO create_suffix;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||3||' month''), ''YYYY-MM'') || ''-01 00:00:00''' INTO from_date;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY-MM'') || ''-01 00:00:00''' INTO to_date;
--计算下一个分区时间
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||3||' month'', ''YYYY-MM-DD'') ' INTO start_time;
END IF;
IF partition_type = 'S' THEN
m_mark = 0;
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month'', ''MM'')::int' INTO m_mark;
IF m_mark > '6' THEN
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY'') ||''07''' INTO create_suffix;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY'') || ''-07-01 00:00:00''' INTO from_date;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||12||' month''), ''YYYY'') || ''-01-01 00:00:00''' INTO to_date;
ELSE
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY'') ||''01''' INTO create_suffix;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY'') || ''-01-01 00:00:00''' INTO from_date;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month''), ''YYYY'') || ''-07-01 00:00:00''' INTO to_date;
END IF;
--计算下一个分区时间
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||6||' month'', ''YYYY-MM-DD'') ' INTO start_time;
END IF;
IF partition_type = 'Y' THEN
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' year''), ''YYYY'') ||''01''' INTO create_suffix;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' year''), ''YYYY'') || ''-01-01 00:00:00''' INTO from_date;
EXECUTE 'SELECT TO_CHAR(date_trunc(''quarter'',to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||2||' year''), ''YYYY'') || ''-01-01 00:00:00''' INTO to_date;
--计算下一个分区时间
EXECUTE 'SELECT TO_CHAR(to_date('''||start_time||''', ''YYYY-MM-DD'') + INTERVAL '''||1||' year'', ''YYYY-MM-DD'') ' INTO start_time;
END IF;
EXECUTE 'SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='''||table_name||'_'||create_suffix||'''' INTO table_exist_mark;
IF table_exist_mark = 0 THEN
/*创建分区表 */
EXECUTE 'CREATE TABLE "'||table_name||'_'||create_suffix||'" PARTITION OF "'||now_schema||'"."'||table_name||'" FOR VALUES FROM ('''||from_date||''') TO ('''||to_date||''')';
/*补充索引*/
/*
EXECUTE 'ALTER TABLE "'||now_schema||'"."'||table_name||'_'||create_suffix||'" ADD PRIMARY KEY ("id")';
EXECUTE 'CREATE INDEX "'||table_name||'_'||create_suffix||'_created_time_idx" ON "'||now_schema||'"."'||table_[1]||'_'||create_suffix||'" USING btree ("created_time")';
*/
END IF;
END IF;
END LOOP;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION "public"."create_partition_fun"("init_time" varchar, "partition_type" varchar, "table_name" varchar) OWNER TO "postgres";
四、设置分区
查询表数据,需要对已有时间的月份和当前及+1创建分区
SELECT create_partition_fun_init('2022-07-01');/**创建8月份分区**/
SELECT create_partition_fun_init('2022-08-01');
SELECT create_partition_fun_init('2022-09-01');
SELECT create_partition_fun_init('2022-10-01');
五、迁移数据
迁移原表(test1)数据至分区表(test_fenqu)
insert into test1_fenqu select * from test1;
六、重命名表
将分区表(test_fenqu)重命名为原表(test1)。
alter table test1 rename to test1_bak;
alter table test1_fenqu rename to test1;
注意索引问题