PostgreSQL 用 CTE语法 + 继承 实现平滑拆分大表

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介:

标签

PostgreSQL , 拆分大表 , 继承 , cte


背景

业务设计初期可能不会考虑到表将来会有多大,或者由于数据日积月累,单表会变得越来越大。

后面在考虑分区的话,应该怎么将单表切换成分区表呢?

这里可以用到PostgreSQL的CTE语法,以及继承功能,还有内置的分区表功能。

例子

具体步骤

1、创建分区表

2、创建继承关系,分区表继承自需要拆分的表

3、用cte转移数据

4、全部转移完成后,在事务中切换表名

例子,将tbl_big切换成哈希分区

1、创建被迁移的大表

create table tbl_big (id int primary key, info text, crt_time timestamp);  
  
create index idx_tbl_big on tbl_big (crt_time);  
  
insert into tbl_big select generate_series(1,10000000);  

2、创建分区表

create table tbl ( like tbl_big including all ) ;    
  
  
  
do language plpgsql $$    
declare    
  parts int := 4;    
begin    
  for i in 0..parts-1 loop    
    execute format('create table tbl%s (like tbl including all) inherits (tbl)', i);    
    execute format('alter table tbl%s add constraint ck check(mod(id,%s)=%s)', i, parts, i);    
  end loop;    
end;    
$$;   
  
  
  
create or replace function ins_tbl() returns trigger as $$    
declare    
begin    
  case abs(mod(NEW.id,4))    
    when 0 then    
      insert into tbl0 values (NEW.*);    
    when 1 then    
      insert into tbl1 values (NEW.*);    
    when 2 then    
      insert into tbl2 values (NEW.*);    
    when 3 then    
      insert into tbl3 values (NEW.*);    
    else    
      return NEW;  -- 如果是NULL则写本地父表    
    end case;    
    return null;    
end;    
$$ language plpgsql strict;    
  
    
  
create trigger tg1 before insert on tbl for each row when (NEW.id is not null) execute procedure ins_tbl();    

3、分区表,继承自被迁移的表

alter table tbl inherit tbl_big;  

4、迁移数据

with tmp as (delete from only tbl_big returning *) insert into tbl select * from tmp;  
-- 如果觉得这样做太久了(一次迁移了所有记录),可以拆成一个个小任务来做  
  
-- 一次迁移10万条,多次调用来完成迁移。  
with tmp as (delete from only tbl_big where ctid = any(array(select ctid from only tbl_big limit 100000)) returning *) insert into tbl select * from tmp;  

5、迁移完成后,切换表名。

postgres=# begin;  
  
postgres=# lock table tbl_big in access exclusive mode ;  
  
postgres=# select count(*) from  only tbl_big;  
  count    
---------  
 0  
(1 row)  
  
postgres=# alter table tbl_big rename to tmp_tbl_big;  
  
postgres=#  alter table tbl no inherit tmp_tbl_big;  
  
postgres=# alter table tbl rename to tbl_big;  
  
postgres=# end;  

参考

《PostgreSQL 传统 hash 分区方法和性能》

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

《PostgreSQL 10.0 preview 功能增强 - 内置分区表》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
5天前
|
关系型数据库 MySQL
Mysql常用语法总结
Mysql常用语法总结
24 0
|
5天前
|
SQL 关系型数据库 MySQL
MySQL 数据库基本语法
SQL,全称Structured Query Language(结构化查询语言),是一种用于管理关系型数据库(RDBMS)的编程语言。SQL用于创建、修改、查询和删除数据库中的数据,以及定义数据库架构。它是数据库管理系统(DBMS)与应用程序之间的标准通信协议。
80 6
|
5天前
|
SQL 关系型数据库 MySQL
Linux对MySQL语法校验
【5月更文挑战第4天】
|
5天前
|
关系型数据库 PostgreSQL
postgresql字符串拼接语法
【5月更文挑战第6天】postgresql字符串拼接语法
8 0
|
5天前
|
SQL 关系型数据库 MySQL
MySQL 基本概念 基础用法 增删改查(特殊查询)语法 详细篇
MySQL 基本概念 基础用法 增删改查(特殊查询)语法 详细篇
|
5天前
|
关系型数据库 MySQL 数据库
【MySQL-10】DCL-数据控制语言-【管理用户&权限控制】 (语法语句&案例演示&可cv案例代码)
【MySQL-10】DCL-数据控制语言-【管理用户&权限控制】 (语法语句&案例演示&可cv案例代码)
【MySQL-10】DCL-数据控制语言-【管理用户&权限控制】 (语法语句&案例演示&可cv案例代码)
|
5天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-案例练习-DQL基本介绍&语法&执行顺序(代码演示)
【MySQL】DQL-案例练习-DQL基本介绍&语法&执行顺序(代码演示)
|
5天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&注意事项&可cv例题语句
|
5天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句
【MySQL】DQL-排序查询-语法&排序方式&注意事项&可cv例题语句
|
5天前
|
SQL 关系型数据库 MySQL
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句
【MySQL】DQL-分组查询-语法&where与having的区别&注意事项&可cv例题语句

相关产品

  • 云原生数据库 PolarDB