PostgreSQL:内置分区表

语法

-- 主表
CREATE TABLE table_name (...)
    [ PARTITION BY { RANGE | LIST } ( {column_name | (expression) } ) ]
    
-- 分区
CREATE TABLE table_name
    PARTITION OF parent_table [ (
    )] FOR VALUES partition_bount_spec

创建分区表

  1. 创建父表,指定分区键和分区策略

    CREATE TABLE log_par (
        id serial,
        user_id int4,
        create_time timestamp(0) without time zone
    ) PARTITION BY RANGE(create_time)
  2. 创建分区,创建分区时指定分区表的父表和分区键的取值范围,注意分区键的范围不要有重叠,否则会报错。

    CREATE TABLE log_par_his PARTITION OF log_par FOR VALUES FROM (UNBOUNDED) TO ('2020-01-01');
    CREATE TABLE log_par_202001 PARTITION OF log_par FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
    CREATE TABLE log_par_202002 PARTITION OF log_par FOR VALUES FROM ('2020-02-01') TO ('2020-03-01');
    .....
  3. 在分区上创建相应索引,通常情况下分区键上的索引是必须的,非分区键的索引可根据实际应用场景选择是否创建。

    CREATE INDEX idx_log_par_his_ctime ON log_par_his USING btree(create_time);
    CREATE INDEX idx_log_par_202001_ctime ON log_par_202001 USING btree(create_time);
    CREATE INDEX idx_log_par_202002_ctime ON log_par_202002 USING btree(create_time);
    .....

添加分区

CREATE TABLE log_par_202101 PARTITION OF log_par FOR VALUES FROM ('2021-01-01') TO ('2021-02-01');
 
CREATE INDEX idx_log_par_202101_ctime ON log_par_202101 USING btree(create_time);

删除分区

  1. 直接删分区

    DROP TABLE log_par_202001
  2. 解绑分区

    -- 解绑分区
    ALTER TABLE log_par DETACH PARTITION log_par_202001;
     
    -- 挂载分区
    ALTER TABLE log_par ATTACH PARTITION log_par_202001 FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');

constraint_exclusion 参数

  • ON:所有表都通过约束优化查询

  • OFF:所有表都不通过约束优化查询

  • PARTITION:只有继承表和 UNION ALL 子查询通过检索约束来优化查询;

注意事项

  • 当往父表插入数据时,数据会自动根据分区键路由规则插入到分区中,目前仅支持范围分区和列表分区。

  • 分区表上的索引、约束需使用单独的命令创建,目前没办法一次性自动在所有分区上创建索引、约束。

  • 内置分区表不支持定义(全局)主键,在分区表的分区上创建主键是可以的。

  • 内置分区表的内部实现使用了继承。

  • 如果 UPDATE 语句的新纪录违反当前分区键的约束则会报错,UPDATE 语句的新纪录目前不支持跨分区的情况。

  • 性能方面:内置分区表根据分区键查询相比普通表性能差距较大,因为这种场景分区表的执行计划会扫描所有分区;根据分区键查询相比普通飙性能有小幅降低,而查询分区表子表性能相比普通表略有提升。

请使用浏览器的分享功能分享到微信等