Skip to content

原生分区表

分区表

数据库分区是一种将数据做物理分片的数据库设计技术,虽然分区技术可以有多种实现方法,

但其主要目的是为了在特定的SQL操作中减少数据读取的总量以缩减响应时间。

使用分区表对应用程序是透明的,对于INSERT,UPDATE,DELETE,SELECT操作,都只需要对父表tbl进行操作,而无需关心操作哪一张子表。

分区方式

  • 水平分区

比如按照时间维度进行划分,订单时间。

水平分区划分方式 HASH , LIST , RANGE

  • 垂直分区

范式规范 : 订单数据 (客户表,商品表,订单表)

优点

  • 性能提升。针对具体范围查询或点查询。
  • 数据管理。 归档,删除。特别是以一个分区做为操作单元。
  • 数据库管理。统计信息,vacuum, repack 操作等

注意事项

  • 分区键选取,如表单的创建时间。
  • 分区大小的划分。一个表多大时开始考虑分区。一个分区多大比较合适。(综合具体业务)
  • 分区表数量控制。过多的分区表可能是一种灾难。可以考虑合并分区,归档数据。
  • 默认分区
  • 表结构更改对现有表结构的影响。更新父表结构对已有子表结构的影响。
  • 索引操作,对子表无效
  • 分区键更新
  • 主键,唯一键约束。 全局还是子表有效。(唯一键+分区键),主表的主键,唯一键必须包含分区键。
  • 新分区创建方式。比如按照月分区,下个月的子表是手动还是自动创建。自动创建对新插入数据的分区键时间需要严格验证。
  • enable_partition_pruning 需要开启

使用限制

  • 没有办法创建跨越所有分区的排除约束,只可能单个约束每个叶子分区。
  • 分区表上的惟一约束(也就是主键)必须包括所有分区键列。存在此限制是因为PostgreSQL只能每个分区中分别强制实施唯一性。

普通表转换为分区表

  • pg 版本 < 12 利用pathman 可在线平滑转换
  • pg 版本 >=12 原始方式

思路:

1 新建一张结构完全相同的表,

2 将原表作为新表子表

3 修改对换表名 (过程加锁)

分区表示例

  • LIST 分区
CREATE TABLE tbl_list(
  id bigserial,
  ival int,
  cval char(1),
  dval timestamp default now(),
  primary key(id, ival)
) partition by list(ival);
create table tbl_list_0 partition of tbl_list for values in (0);
create table tbl_list_1_2 partition of tbl_list for values in (1,2);
create table tbl_list_default partition of tbl_list default;

  • RANGE 分区
CREATE TABLE tbl_range(
  id bigserial,
  ival int,
  cval char(1),
  dval timestamp default now(),
  primary key(id, dval)
) partition by range(dval);
create table tbl_range_202001 partition of tbl_range for values from ('2020-01-01 00:00:00') to ('2020-02-01 00:00:00');
create table tbl_range_202002 partition of tbl_range for values from ('2020-02-01 00:00:00') to ('2020-03-01 00:00:00');
create table tbl_range_default partition of tbl_range default;

  • HASH 分区 ,不能包含默认分区
CREATE TABLE tbl_hash(
  id bigserial,
  ival int,
  cval char(1),
  dval timestamp default now(),
  primary key(id, ival)
) partition by hash(ival);
create table tbl_hash_0 partition of tbl_hash for values WITH (MODULUS 3, REMAINDER 0);
create table tbl_hash_1 partition of tbl_hash for values WITH (MODULUS 3, REMAINDER 1);
create table tbl_hash_2 partition of tbl_hash for values WITH (MODULUS 3, REMAINDER 2);