PostgreSQL 基于 inherits 实现分表的示例代码

 更新时间:2026年05月12日 08:54:58   作者:倒流时光三十年  
本文主要介绍了PostgreSQL 基于 inherits 实现分表的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

背景

生产环境有一张 sales_order_full 表数据量达到 3.3 亿. 存储了公司4个大区全量销售数据.并且数据量还在持续增长. 数据量过大对业务功能读写都造成极大的 IO 压力.为保证系统稳定,团队制定了短期的计划,对 sales_order_full  表按大区进行拆分.来减轻单表压力.

首先你需要了解 PostgreSQL 的 inherits  技术

在 PostgreSQL 中,INHERITANCE 是一种特性,允许一个表从另一个表继承属性(如列、约束等)。这意味着,如果一个表继承自另一个表,它将自动获得所有父表的列和约束。这对于简化数据库设计,特别是当你想要在不同的层次中共享相同结构的数据时非常有用。 (解释来自百度)       

分析订单 Full 表

CREATE TABLE "public"."sales_order_full" (
  "id" int8 NOT NULL DEFAULT nextval('sales_order_mixed_id_seq'::regclass),
  "version_number varchar",
  "order_id" varchar(298),
  "country_cd varchar(29)", 
  "product_no" varchar(35),
  "serial_no" varchar(273),
  "qty" int4,
  "fiscal_qtr",
  "order_dt" time,
  PRIMARY KEY ("order_id")
)
  • ID: 自增索引序列.当前索引序列值已很大 
  • order_id: 订单ID,唯一主键
  • country_cd: 通过country_cd 从 sales_geo_config 表中匹配所属大区 (历史原因导致).                                                                                              

拆分思路

  1. 重建 sales_order_full  表
  2. 放弃 sales_order_mixed_id_seq 重建 id 索引.
  3. full 增加区域字段.便于数据分表
  4. 初始化子表并初始化数据
  5. 代码逻辑调整

定义分表

sales_order_full [主表]只做请求转发.不存储任何数据
ales_order_full_cp     存储 geo =  CP 区域数据
sales_order_full_hd存储 geo =  HD 区域数据
sales_order_full_cy存储 geo =  CY 区域数据
sales_order_full_sy存储 geo =  SY 区域数据
sales_order_full_unkonw兜底未匹配出区域的数据 

前期工作

原 sales_order_full 表改名为  sales_order_full_all_data_bak

第一步:创建新 Full 表

CREATE TABLE "public"."sales_order_full" (
  "id" bigserial, -- bigserial 会自动创建名为 sales_order_full_id_seq 自增索引
  "version_number varchar",
  "order_id" varchar(298),
  "country_cd varchar(29)", 
  "product_no" varchar(35),
  "serial_no" varchar(273),
  "qty" int4,
  "fiscal_qtr", 
  "geo", --所属大区
  "order_dt" time,
  PRIMARY KEY ("order_id")
)

第二步: 创建子表

因为分表较少.没有必要动态创建.统一进行分表初始化即可.

inherits 方式创建的子表. 索引需要重新设置.

子表中 id 字段会复用主表中的 ID 自增索引.

CHECK(geo = 'CP') 意思是对 geo 字段进行约束.只能存储 CP 大区数据.

-- 创建子表,并设置 full 表的父子关系
create table IF NOT EXISTS "sales_order_full_cp" (CHECK(geo = 'CP')) 
inherits (sales_order_full);

-- 设置主键信息
ALTER TABLE "sales_order_full_cp" ADD CONSTRAINT "sales_order_full_cp_pkey" 
PRIMARY KEY (order_id);

-- 设置对应索引
CREATE INDEX "sales_order_full_cp_mixed_idx" ON "public"."sales_order_full_cp" 
USING btree (
  "fiscal_qtr",
  "order_id",
  "country_cd"    
);
      

第三步:数据流转子表

处理明确 Geo 的数据

 insert into sales_order_full_cp
 (order_id,geo,country_cd,product_no,serial_no,qty,fiscal_qtr,order_dt,version_number)
 select 
 -- 注意 geo 字段取自 sales_geo_config 表
 a.order_id,b.geo,a.country_cd,a.product_no,a.serial_no,a.qty,a.fiscal_qtr,a.order_dt,version_number
 from 
 sales_order_full_cp_all_data_bak a 
 left join sales_geo_config b on a.country_cd = b.country 
 where b.geo = 'CP';

处理 unkonw 因为这类数据没有明确Geo,所以要设置默认值 'UNKNOWN'

 insert into sales_order_full_unknown
 (order_id,geo,country_cd,product_no,serial_no,qty,fiscal_qtr,order_dt,versionnumber)
 select 
 -- 注意 geo 直接默认
 a.order_id,'UNKNOWN',a.country_cd,a.product_no,a.serial_no,a.qty,a.fiscal_qtr,a.order_dt,versionnumber
 from 
 sales_order_full_cp_all_data_bak a 
 left join sales_geo_config b on a.country_cd = b.country 
 where b.geo is null or b.geo not in ('HD','CY','SY','CP');

第四步:数据对比并清理 sales_order_full_all_data_bak 表

注意这里得 select count(*) from sales_order_full;

再强调一遍: sales_order_full 表不存储任何数据,只做调用的中转。

通过 Explan 查看执行过程(简略):

->  Parallel Index Only Scan using sales_order_full_unknown 
->  Parallel Seq Scan on sales_order_full_cp 
->  Parallel Seq Scan on sales_order_full_cy
->  Parallel Seq Scan on sales_order_sy
->  Parallel Seq Scan on sales_order_full_hd

可以看到.数据来源全部来自5张子表. 

select count(*) from sales_order_full;
result: 330000000  

select count(*) from sales_order_all_data_bak;
result: 330000000

-- 结果相等 直接删,释放数据库空间
drop table  sales_order_all_data_bak; 

第五步:调整代码逻辑

  1. 对 sales_order_full 表查询操作,要求指定 geo 精确分表信息.
select * from sales_order_full where geo = 'HD' and xx = 'xx'
或
select * from sales_order_full_hd where xx = 'xx'
  1. 新增修改操作必须精确到具体子表操作.
 insert into sales_order_full_cp
 (order_id,geo,country_cd,product_no,serial_no,qty,fiscal_qtr,order_dt,version_numer)
 select 
 a.order_id,b.geo,a.country_cd,a.product_no,a.serial_no,a.qty,a.fiscal_qtr,a.order_dt,versionnumber
 from 
 order_inbound inbound
 left join sales_geo_config b on inbound.country_cd = b.country 
 where b.geo = 'CP' and inbound.version_number = '001';



update sales_order_full_cp set order_status = 'Closed' where order_id = 'xx';

疑问1:为什么不用触发器?

有同事疑问,为何不给 sales_order_full 主表创建触发器.这样数据新增就只操作主表.让主表进行转发处理岂不是更方便.

答案自然否定的.起码完全不合适我们. 系统订单全部是批处理的场景.大量数据通过触发器转发会大大降低性能,因为触发器会逐行检查处理.性能损耗无法接受.

疑问2:既然操作都细化到子表. sales_order_full 还有何用?

1.万恶的分页查询场景.假设要全区域分页查询.我们只需操作 sales_order_full 表. 由数据库帮我们完成 limit 和 offset . 不需要自己控制 5 张子表的分页.

2.对子表的结构修改.只需调整 sales_order_full 表.调整会自动同步到子表.

疑问3:为何不用成熟分表方案.如 Sharding-JDBC?

数据库自带的就超好用了.非常轻量.处理只依赖数据库 IO. 不占应用内存

到此这篇关于PostgreSQL 基于 inherits 实现分表的示例代码的文章就介绍到这了,更多相关PostgreSQL inherits分表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!​

相关文章

  • postgresql insert into select无法使用并行查询的解决

    postgresql insert into select无法使用并行查询的解决

    这篇文章主要介绍了postgresql insert into select无法使用并行查询的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • PostgreSQL如何选择合适的数据类型

    PostgreSQL如何选择合适的数据类型

    本文详细介绍了PostgreSQL中各种数据类型的特性、适用场景、潜在陷阱及最佳实践,涵盖了数值、字符、时间、布尔、枚举、网络、JSON、几何、全文搜索、范围、自定义类型等核心类别,并通过真实案例说明了数据类型选型的逻辑,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • Postgresql的select优化操作(快了200倍)

    Postgresql的select优化操作(快了200倍)

    这篇文章主要介绍了Postgresql的select优化操作(快了200倍),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • SpringBoot连接使用PostgreSql数据库的方法

    SpringBoot连接使用PostgreSql数据库的方法

    这篇文章主要介绍了SpringBoot连接使用PostgreSql数据库的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • PostgreSQL扩展UUID-OSSP的使用方法

    PostgreSQL扩展UUID-OSSP的使用方法

    UUID-OSSP是PostgreSQL提供的一个扩展模块,用于生成符合标准的 UUID,下面就来介绍一下PostgreSQL扩展UUID-OSSP的使用方法,具有一定的参考价值,感兴趣的可以了解一下
    2025-07-07
  • PostgreSQL并行计算算法及参数强制并行度设置方法

    PostgreSQL并行计算算法及参数强制并行度设置方法

    这篇文章主要介绍了PostgreSQL 并行计算算法,参数,强制并行度设置,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • PostgreSQL新手入门教程

    PostgreSQL新手入门教程

    本文介绍PostgreSQL的安装和基本用法,供初次使用者上手。以下内容基于Debian操作系统,其他操作系统实在没有精力兼顾,但是大部分内容应该普遍适用
    2014-06-06
  • 最详细安装 PostgreSQL方法及常见问题解决

    最详细安装 PostgreSQL方法及常见问题解决

    这篇文章主要介绍了最详细安装 PostgreSQL方法及常见问题解决,介绍了在 Windows 系统上安装 PostgreSQL及 Linux 系统上安装 PostgreSQL的方法,感兴趣的朋友一起看看吧
    2025-04-04
  • Ubuntu PostgreSQL安装和配置的介绍

    Ubuntu PostgreSQL安装和配置的介绍

    今天小编就为大家分享一篇关于Ubuntu PostgreSQL安装和配置的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • PostgreSQL数据库timestamp数据类型精度进位问题解析

    PostgreSQL数据库timestamp数据类型精度进位问题解析

    PostgreSQL是一款功能强大的开源关系型数据库管理系统,起源于1986年的POSTGRES项目,它支持多种数据类型,包括数值类型、字符串类型、日期时间类型等,本文介绍PostgreSQL数据库timestamp数据类型精度进位问题,感兴趣的朋友一起看看吧
    2024-11-11

最新评论