postgresql分区表代码创建方案

这里主要刷针对的范围分区,其它类型分区表的场景没有遇见过,一般来说都是使用分区插件管理。我还是提供一个代码处理的思路。

1.首先分区表中至少有一个范围分区了,这里以时间作为分区。主要是提供一个分区增长的策略。

2.通过前面的sql查询数据库中的分区表信息。

3.逐个解析分区表。

思路:分区表都是时间分区,分区范围小时、天、月、季度建立,不会到分钟的粒度。定时检测,通过配置设置,预留的分区和需要一次创建的分区个数。当前时间到达预留分区时,立即创建分区。例如以天创建分区,预留3天,一次创建90天。则当前时间与数据库最后一个分区时间对比,已经到达最后三天,则立即创建已有分区的后90天分区。如果今天是8号,则分区表中最后一个是11号,则立即创建11号后90天的分区。

给大家贴一个关键代码,代码考虑,以下代码:

java 复制代码
package org.db.partition.task;

import org.db.partition.configuration.PartDBConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class PartitionedTableTask implements CommandLineRunner {
    @Autowired
    PartDBConfig partDBConfig;

    //查询分区
    String sql="select *  FROM ( SELECT parent.relname parent,\n" +
            "        child.relname child,\n" +
            "                CASE WHEN child.relispartition THEN pg_get_expr(child.relpartbound, child.oid) ELSE NULL END AS\n" +
            " partition_bound\n" +
            "FROM pg_inherits\n" +
            "JOIN pg_class parent ON pg_inherits.inhparent = parent.oid\n" +
            "JOIN pg_class child  ON pg_inherits.inhrelid  = child.oid)  as part\n" +
            "\n" +
            "WHERE partition_bound is not null  ORDER BY partition_bound\n";

    //创建分区,参数顺序 分区表名、父表、分区范围
    String format="CREATE TABLE %s PARTITION OF %s\n" +
            "    \n" +
            "FOR VALUES FROM ('%s') TO ('%s');";

    @Override
    public void run(String... args) throws Exception {
        while (true) {
            Connection connection = DBUtil.getConnection(partDBConfig);
            try {
                Statement statement = connection.createStatement();
                ResultSet rs = statement.executeQuery(sql);
                List<ChildTable> list = new ArrayList<ChildTable>();
                while (rs.next()) {
                    ChildTable childTable = new ChildTable();
                    childTable.setParent(rs.getString("parent"));
                    childTable.setChild(rs.getString("child"));
                    childTable.setBound(rs.getString("partition_bound"));
                    list.add(childTable);
                }

                //按照父表分组
                Map<String, List<ChildTable>> groupedBy = list.stream()
                        .collect(Collectors.groupingBy(ChildTable::getParent));

                groupedBy.forEach((parent, child) -> {
                    try {
                        //取出最后一个分区
                        ChildTable table = child.get(child.size() - 1);

                        /**
                         * 获取分区范围,正则表达式提取时间
                         * FOR VALUES FROM ('2025-01-01') TO ('2025-04-01')
                         */
                        table.process();
                        if (table.getEnd() != null) {
                            LocalDateTime now = LocalDateTime.now();
                            //分区开始
                            LocalDateTime startTime = AutoDateParser.parse(table.getStart());

                            //分区结束
                            LocalDateTime endTime = AutoDateParser.parse(table.getEnd());

                            //计算一个分区时长
                            long minutesBetween = ChronoUnit.MINUTES.between(startTime, endTime);
                            //计算当前时间到最后一个分区的时间
                            long secondsBetween = ChronoUnit.SECONDS.between(now, endTime);
                            //如果当前时间到最后一个分区的时间小于预留的时间
                            if (secondsBetween < partDBConfig.getNum() * minutesBetween) {
                                //开始创建
                                LocalDateTime nextTime = endTime;
                                //需要一次创建的分区个数
                                for (int i = 0; i < partDBConfig.getPre(); i++) {
                                    LocalDateTime addTime = nextTime.plus(Duration.ofMinutes(minutesBetween));
                                    String name = addTime.format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH"));
                                    String add = String.format(format, "part_" + name, table.getParent(), nextTime, addTime);
                                    try {
                                        connection.createStatement().execute(add);
                                    } catch (SQLException e) {
                                        throw new RuntimeException(e);
                                    }
                                    //
                                    nextTime = addTime;
                                }
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                });
                DBUtil.closeJDBC(rs, statement, connection);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
           Thread.sleep(1000*60*50);
        }
    }
}
相关推荐
字节跳动数据平台18 小时前
5000 字技术向拆解 | 火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
武子康1 天前
大数据-239 离线数仓 - 广告业务实战:Flume 导入日志到 HDFS,并完成 Hive ODS/DWD 分层加载
大数据·后端·apache hive
字节跳动数据平台2 天前
代码量减少 70%、GPU 利用率达 95%:火山引擎多模态数据湖如何释放模思智能的算法生产力
大数据
得物技术2 天前
深入剖析Spark UI界面:参数与界面详解|得物技术
大数据·后端·spark
武子康2 天前
大数据-238 离线数仓 - 广告业务 Hive分析实战:ADS 点击率、购买率与 Top100 排名避坑
大数据·后端·apache hive
武子康3 天前
大数据-237 离线数仓 - Hive 广告业务实战:ODS→DWD 事件解析、广告明细与转化分析落地
大数据·后端·apache hive
大大大大晴天3 天前
Flink生产问题排障-Kryo serializer scala extensions are not available
大数据·flink
武子康5 天前
大数据-236 离线数仓 - 会员指标验证、DataX 导出与广告业务 ODS/DWD/ADS 全流程
大数据·后端·apache hive
武子康6 天前
大数据-235 离线数仓 - 实战:Flume+HDFS+Hive 搭建 ODS/DWD/DWS/ADS 会员分析链路
大数据·后端·apache hive
DianSan_ERP7 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet