postgreSQL创建表分区

postgreSQL创建表分区

1.范围分区介绍

复制代码
范围分区是根据某个列的范围来进行分区。常用于日期、时间或其他连续值类型的列。例如,按日期字段对表进行分区。

2.创建表

复制代码
创建分区时使用的复合主键,所以在代码中如果集成了mybatisplus,不要使用selectById等类似方法,而是使用QueryWrapper查询。
sql 复制代码
CREATE TABLE "public"."car" (
  "id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL,
  "plate_no" varchar(255) COLLATE "pg_catalog"."default",
  "create_time" timestamp(6),
  "car_id" varchar(64) COLLATE "pg_catalog"."default",
  "height" varchar(64) COLLATE "pg_catalog"."default",
  CONSTRAINT "car_partition_pkey" PRIMARY KEY ("id","create_time")
) PARTITION BY RANGE (
  "create_time" "pg_catalog"."timestamp_ops"
)
;

3.每月创建分区函数

sql 复制代码
CREATE OR REPLACE FUNCTION "public"."monthly_partition"()
  RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
    start_date TIMESTAMP;
    end_date TIMESTAMP;
    partition_name TEXT;
		partition_date TEXT;
BEGIN
    -- 获取当前日期的下个月的第一天
    start_date := date_trunc('month', CURRENT_DATE) + INTERVAL '1 month';
    -- 获取下个月的最后一天
    end_date := start_date + INTERVAL '1 month';

    -- 动态生成car分区表的名称
    partition_name := 'car_' || TO_CHAR(start_date, 'YYYY_MM');
    
    -- 创建car分区表
    EXECUTE format(
        'CREATE TABLE IF NOT EXISTS %I PARTITION OF car FOR VALUES FROM (%L) TO (%L)',
        partition_name, start_date, end_date
    );
                
                    -- 动态生成car分区表的名称
    partition_name := 'car_' || TO_CHAR(start_date, 'YYYY_MM');
    
    -- 创建car分区表
    EXECUTE format(
        'CREATE TABLE IF NOT EXISTS %I PARTITION OF car FOR VALUES FROM (%L) TO (%L)',
        partition_name, start_date, end_date
    );
		
		-- 为分区动态创建索引
        EXECUTE format(
            'CREATE INDEX IF NOT EXISTS plate_no_car_id_idx_%s ON %I (
                plate_no,
                car_id
            )',
            partition_date, partition_name
        );
    

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

4.调用函数

在数据库中执行一次

sql 复制代码
SELECT monthly_partition();

注:如果每月创建一个分区,可以通过定时任务调用数据库函数。(通过定时任务调用,每月执行一次)

在mapper中定义方法

java 复制代码
String createMonthlyPartition();

然后在xml中编写sql

xml 复制代码
    <select id="createMonthlyPartition" statementType="CALLABLE" resultType="java.lang.String" >
        {call monthly_partition()}
    </select>

5.历史数据按月创建分区

如果旧表没有创建分区,重新建表分区后,必须要根据时间字段创建分区后才能导入数据。创建分区可以执行下面脚本。(只需执行一次)

sql 复制代码
DO $$
DECLARE
    start_date DATE := '2024-01-01';  -- 起始日期,建议设置为月份的第一天
    current_date DATE := CURRENT_DATE; -- 当前日期
    partition_name TEXT;
    start_time TIMESTAMP;
    end_time TIMESTAMP;
    d DATE;  -- 声明变量 d 为 DATE 类型
BEGIN
    -- 使用 generate_series 生成从 start_date 到 current_date 的月份范围
    FOR d IN 
        SELECT date_trunc('month', generate_series(start_date, current_date, '1 month'::INTERVAL))
    LOOP
        -- 为每个月生成对应的时间范围
        start_time := d;
        end_time := d + INTERVAL '1 month';

        -- 动态生成分区名称
        partition_name := 'car_' || TO_CHAR(d, 'YYYY_MM');

        -- 创建分区
        EXECUTE format(
            'CREATE TABLE IF NOT EXISTS %I PARTITION OF car 
             FOR VALUES FROM (%L) TO (%L)',
            partition_name, start_time, end_time
        );
    END LOOP;
END $$;

6.查看、删除分区索引

查看分区索引

sql 复制代码
SELECT * FROM pg_indexes WHERE tablename = 'car_2025_01';

删除分区索引。plate_no_car_id_idx_为索引名

sql 复制代码
DROP INDEX IF EXISTS plate_no_car_id_idx_;
相关推荐
VALENIAN瓦伦尼安教学设备5 分钟前
设备对中不良的危害
数据库·嵌入式硬件·算法
yyt3630458417 分钟前
spring单例bean线程安全问题讨论
java·spring
小兔崽子去哪了17 分钟前
Docker 安装 PostgreSQL
数据库·后端·postgresql
野犬寒鸦21 分钟前
Redis热点key问题解析与实战解决方案(附大厂实际方案讲解)
服务器·数据库·redis·后端·缓存·bootstrap
我是大猴子27 分钟前
事务失效的几种情况以及是为什么(详解)
java·开发语言
mldlds1 小时前
Windows安装Redis图文教程
数据库·windows·redis
wertyuytrewm1 小时前
Java面试——Java基础
java·jvm·面试
czlczl200209251 小时前
RAG实现思路流程
java·jvm
带娃的IT创业者1 小时前
WeClaw_40_系统监控与日志体系:多层次日志架构与Trace追踪
java·开发语言·python·架构·系统监控·日志系统·链路追踪
Y001112361 小时前
JDBC原理
java·开发语言·数据库·jdbc