Postgresql建分区表步骤sql

该博客介绍了在业务扩展中如何利用PostgreSQL进行表分区以提升查询效率。首先,通过备份、删除和创建带分区的新表来实现表的转换。接着,创建了针对分区表的索引和主键约束,并定义了一个函数用于动态创建分区。最后,将历史数据导入到默认分区,并执行函数创建指定日期范围的分区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于业务发展,需要对系统表进行分区处理,以提高查询速度,下面代码是示例,以partition_table_name表为例。

--备份表
SELECT * INTO partition_table_name_2022_bak FROM partition_table_name;
--删除原表
DROP TABLE IF EXISTS "public"."partition_table_name";
--创建带分区的原表
CREATE TABLE "public"."partition_table_name" (
  "id" int8 NOT NULL DEFAULT '-1'::integer,
  "tenant_id" int8 NOT NULL DEFAULT '-1'::integer,
  "app_id" int8 NOT NULL DEFAULT '-1'::integer,
  "data_id" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
  "data_type" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
  "data_version" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "data_format" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
  "data_source" varchar(32) COLLATE "pg_catalog"."default",
  "data" text COLLATE "pg_catalog"."default",
  "status" char(1) COLLATE "pg_catalog"."default" NOT NULL,
  "status_time" timestamp(6),
  "create_time" timestamp(6) NOT NULL
)
--分区字段 可支持多个
PARTITION BY RANGE (
  "create_time"
)
;
//创建默认分区
CREATE TABLE IF NOT EXISTS SWAP_DATA_INFO_DEFAULT PARTITION OF SWAP_DATA_INFO DEFAULT;
--索引
CREATE INDEX "idx_partition_table_name_1" ON "public"."partition_table_name" USING btree (
  "data_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "idx_partition_table_name_2" ON "public"."partition_table_name" USING btree (
  "tenant_id" "pg_catalog"."int8_ops" ASC NULLS LAST
);
CREATE INDEX "idx_partition_table_name_3" ON "public"."partition_table_name" USING btree (
  "create_time" "pg_catalog"."timestamp_ops" ASC NULLS LAST
);

ALTER TABLE "public"."partition_table_name" ADD CONSTRAINT "pk_partition_table_name" PRIMARY KEY ("id","create_time");

--创建分区表函数
CREATE OR REPLACE FUNCTION public.create_daypartition_by_day(v_tablename character varying, v_start_day character varying, v_end_day character varying)
 RETURNS void
 LANGUAGE plpgsql
AS $function$
DECLARE vt_i integer;  vd_i integer; vn_day date; vn_next_day date; vn_num_day varchar;  vn_day_num integer;
BEGIN
        select count(tablename) into vt_i from  pg_tables where tablename=v_tablename||'_'||to_char(v_end_day :: DATE, 'yyyyMMdd');
        if vt_i = 0 then

select (v_end_day::date - v_start_day::date) into vn_day_num;
for vd_i in 0..vn_day_num loop
vn_day := v_start_day :: DATE + (vd_i || ' day') :: INTERVAL ;

vn_next_day := vn_day + INTERVAL '1 day' ;

 vn_num_day := to_char(vn_day, 'yyyyMMdd') ; 

 EXECUTE 'create table ' || v_tablename || '_' || vn_num_day || ' partition of ' || v_tablename || ' for values from (''' || vn_day || ' 00:00:00'') to (''' || vn_next_day || ' 00:00:00'');' ;
end loop;

  else  
      RAISE EXCEPTION 'partition table % exist!',v_tablename ||'_' ||v_start_day; 
  end if;
END ; $function$;

set lock_timeout = 9999999;

--执行创建分区表函数
select create_daypartition_by_day('partition_table_name','2022-07-01','2022-09-30');
select create_daypartition_by_day('partition_table_name','2022-10-01','2022-12-01');

--历史数据放进默认分区
INSERT INTO partition_table_name SELECT * FROM partition_table_name_bak;

<think>嗯,用户想了解如何在PostgreSQL创建和管理分区表。我之前已经处理过类似的问题,所以需要回忆一下相关的知识。首先,PostgreSQL支持的分区类型有范围分区、列表分区和哈希分区。我记得每个分区策略有不同的适用场景,比如范围分区适合按时间或数值范围划分数据,列表分区适合按特定值,而哈希分区则用于均匀分布数据。 用户可能需要具体的步骤和示例,所以我得详细说明创建分区表步骤。例如,创建父表的时候需要指定分区策略,然后创建子表并定义各自的边界条件。不过要注意,不同版本的PostgreSQL可能语法有所不同,尤其是原生分区表功能是在10版本引入的,之后每个版本可能有改进。所以需要提到版本差异,并议使用较新的版本以获得更好的支持。 然后,管理部分包括添加新分区、删除旧分区分区维护和查询优化。添加分区可能需要使用ALTER TABLE ... ATTACH PARTITION,或者直接创建子表。删除分区则需要注意数据的处理,比如使用DROP TABLE或者DETACH PARTITION。 示例部分很重要,用户可能需要实际的SQL代码来参考。比如,创建一个按时间范围分区的表,然后插入数据并查看执行计划,验证分区是否生效。此外,还需要提到系统表如pg_class和pg_partitioned_table,用于查询分区信息。 用户可能还关心性能优化,比如分区剪枝,这时候需要解释执行计划中的信息,确保查询能正确利用分区。另外,维护操作如索引创建,应该在父表上自动应用到子表,或者需要手动处理,这取决于版本。 还要考虑用户可能遇到的问题,比如分区键的选择,或者如何管理大量分区。比如,使用哈希分区时如何确定分区的数量,或者在范围分区中处理边界值的问题。可能需要提醒用户注意分区数量的管理,避免过多分区影响性能。 另外,引用中的信息提到PostgreSQL源码中的相关文件,虽然用户可能不需要深入代码,但可以提到这些资源供进一步学习。同时,引用[3]中的查询分区条件的方法,应该在管理部分给出示例,如使用pg_get_expr函数查看分区边界。 最后,确保回答结构清晰,分步骤说明创建和管理的方法,提供示例代码,并补充注意事项和最佳实践。可能还需要生成相关问题,比如性能优化、分区策略选择等,帮助用户进一步学习。</think>PostgreSQL创建和管理分区表的完整方法及示例说明如下: ### 一、分区表创建步骤 1. **确定分区策略** - **范围分区**:适用时间序列数据(如日期范围) - **列表分区**:适用离散值分类(如地区代码) - **哈希分区**:适用均匀分布数据(如随机ID) 2. **创建父表**(PostgreSQL 10+原生分区语法) ```sql -- 范围分区示例 CREATE TABLE sales ( id SERIAL, sale_date DATE NOT NULL, amount NUMERIC ) PARTITION BY RANGE (sale_date); -- 列表分区示例 CREATE TABLE region_data ( city_id INT, region_code VARCHAR(5) ) PARTITION BY LIST (region_code); -- 哈希分区示例(PostgreSQL 11+) CREATE TABLE user_logs ( log_id BIGSERIAL, user_id INT ) PARTITION BY HASH (user_id); ``` 3. **创建分区表** ```sql -- 范围子分区 CREATE TABLE sales_2023 PARTITION OF sales FOR VALUES FROM ('2023-01-01') TO ('2024-01-01'); -- 列表子分区 CREATE TABLE region_east PARTITION OF region_data FOR VALUES IN ('BJ', 'SH', 'TJ'); -- 哈希子分区创建4个哈希分区) CREATE TABLE user_logs_1 PARTITION OF user_logs FOR VALUES WITH (MODULUS 4, REMAINDER 0); ``` ### 二、分区表管理操作 1. **动态添加分区** ```sql -- 添加新年度分区 CREATE TABLE sales_2024 PARTITION OF sales FOR VALUES FROM ('2024-01-01') TO ('2025-01-01'); -- 使用ATTACH附加现有表 CREATE TABLE sales_archive (LIKE sales INCLUDING INDEXES); ALTER TABLE sales ATTACH PARTITION sales_archive FOR VALUES FROM ('2000-01-01') TO ('2023-01-01'); ``` 2. **删除分区** ```sql -- 直接删除分区表 DROP TABLE sales_2023; -- 安全移除分区(保留数据) ALTER TABLE sales DETACH PARTITION sales_2023; ``` 3. **分区维护** ```sql -- 创建索引(自动传播到所有分区) CREATE INDEX ON sales (sale_date); -- 手动维护特定分区 VACUUM (ANALYZE) sales_2023; -- 查询分区元数据 SELECT relname, pg_get_expr(relpartbound, oid) FROM pg_class WHERE relpartbound IS NOT NULL; -- [^3] ``` ### 三、使用示例验证 ```sql -- 插入测试数据 INSERT INTO sales (sale_date, amount) VALUES ('2023-06-15', 100.00), ('2024-02-20', 200.00); -- 查看数据分布 EXPLAIN ANALYZE SELECT * FROM sales WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31'; -- 应显示只扫描sales_2023分区[^2] ``` ### 四、注意事项 1. **版本差异**:原生分区功能需PostgreSQL 10+,议使用12+版本获得完整功能 2. **性能优化**: - 使用`CHECK`约束加速查询 - 通过`pg_partition_tree`视图查看分区层次 - 定期执行`ANALYZE`更新统计信息 3. **限制**: - 主键必须包含分区键 - 外键不能引用分区表 - 最大分区默认32GB(可通过配置调整) ### 五、进阶管理技巧 1. **子分区(嵌套分区)** ```sql CREATE TABLE sales_2023_q1 PARTITION OF sales_2023 FOR VALUES FROM ('2023-01-01') TO ('2023-04-01'); ``` 2. **默认分区**(PostgreSQL 11+) ```sql CREATE TABLE sales_default PARTITION OF sales DEFAULT; ``` 3. **分区剪枝验证** ```sql SET enable_partition_pruning = on; EXPLAIN ANALYZE SELECT * FROM sales WHERE sale_date = '2023-07-01'; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值