PostgreSql分区表

一、原始表

/**表**/
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;

注意索引问题

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PostgreSQL 支持分区表,它允许将表数据根据特定的条件拆分成多个子表,从而提高查询性能和管理数据。下面是一些关于 PostgreSQL 分区表的基本信息: 1. 分区表定义:在创建表时,可以使用 PARTITION BY 子句指定分区键。常见的分区键类型包括范围(range)、列表(list)和哈希(hash)。 2. 范围分区(Range partitioning):根据某个列的值范围进行分区,例如按时间范围、按数值范围等。可以使用 CREATE TABLE 语句的 PARTITION OF 子句定义每个分区。 3. 列表分区(List partitioning):根据某个列的值列表进行分区,例如按地区、按部门等。也可以使用 CREATE TABLE 语句的 PARTITION OF 子句定义每个分区。 4. 哈希分区(Hash partitioning):根据某个列的哈希值进行分区,通常用于数据平均分布的场景。使用 CREATE TABLE 语句的 PARTITION OF 子句定义每个分区。 5. 分区表管理:分区表可以通过 ALTER TABLE 添加或删除分区。还可以使用 EXCHANGE PARTITION 子句将数据从非分区表或已有分区中交换进入分区表。 6. 查询优化:PostgreSQL 的查询优化器会在执行查询时自动识别并只查询相关分区,从而提高查询性能。同时,可以通过查询约束来进一步减少查询的分区范围。 需要注意的是,分区表数据库中的使用需要根据具体的业务需求和数据特点来决定,同时需要合理设计和规划分区键,以及考虑数据维护和查询优化等方面的因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值