

Postgresql在市场的运用范围越来越广,分区表的性能在12版本已经得到很大提升,不再采用原来的表继承方式,对使用者越来越友好,以下是分区表使用的一些心得。
建表
CREATE TABLE yxptest (
id serial ,
peaktemp int,
logdate date not null
) PARTITION BY RANGE (logdate);
CREATE TABLE yxptest_p202201 PARTITION OF yxptest FOR VALUES FROM ('2022-01-01') TO ('2022-02-01');
CREATE TABLE yxptest_p202202 PARTITION OF yxptest FOR VALUES FROM ('2022-02-01') TO ('2022-03-01');
。
。
。
CREATE TABLE yxptest_p202211 PARTITION OF yxptest FOR VALUES FROM ('2022-11-01') TO ('2022-12-01');
CREATE TABLE yxptest_p202212 PARTITION OF yxptest FOR VALUES FROM ('2022-12-01') TO ('2023-01-01');
造数据
insert into yxptest (peaktemp,logdate)
select round(100000000*random()),generate_series('2022-01-01'::date,'2022-12-31'::date,'1 minute');
testyxp=# ALTER TABLE yxptest ADD PRIMARY KEY (id);
ERROR: insufficient columns in PRIMARY KEY constraint definition
DETAIL: PRIMARY KEY constraint on table "yxptest" lacks column "logdate" which is part of the partition key.
testyxp=# create index idx_1_yxptest on yxptest (peaktemp);
CREATE INDEX
testyxp=# \d yxptest
Partitioned table "public.yxptest"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('yxptest_id_seq'::regclass)
peaktemp | integer | | |
logdate | date | | not null |
Partition key: RANGE (logdate)
Indexes:
"yxptest_pkey" PRIMARY KEY, btree (id, logdate)
"idx_1_yxptest" btree (peaktemp)
Number of partitions: 12 (Use \d+ to list them.)
testyxp=# \d yxptest_p202211
Table "public.yxptest_p202211"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('yxptest_id_seq'::regclass)
peaktemp | integer | | |
logdate | date | | not null |
Partition of: yxptest FOR VALUES FROM ('2022-11-01') TO ('2022-12-01')
Indexes:
"yxptest_p202211_pkey" PRIMARY KEY, btree (id, logdate)
"yxptest_p202211_peaktemp_idx" btree (peaktemp)
testyxp=# CREATE TABLE yxptest_p202301 PARTITION OF yxptest FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');
CREATE TABLE
testyxp=# \d yxptest_p202301
Table "public.yxptest_p202301"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('yxptest_id_seq'::regclass)
peaktemp | integer | | |
logdate | date | | not null |
Partition of: yxptest FOR VALUES FROM ('2023-01-01') TO ('2023-02-01')
Indexes:
"yxptest_p202301_pkey" PRIMARY KEY, btree (id, logdate)
"yxptest_p202301_peaktemp_idx" btree (peaktemp)
现在来说已经方便很多,大大减少维护量。
testyxp=# alter table yxptest DETACH partition yxptest_p202201;
ALTER TABLE
testyxp=# alter table yxptest_p202201 rename to yxptest_p202201_b;
ALTER TABLE
testyxp=# CREATE TABLE yxptest_p202201 (
testyxp(# id serial ,
testyxp(# peaktemp int,
testyxp(# logdate date not null
testyxp(# ) PARTITION BY RANGE (logdate);
CREATE TABLE
testyxp=# CREATE TABLE yxptest_p202201_1 partition of yxptest_p202201 FOR VALUES FROM ('2022-01-01') TO ('2022-01-10');
CREATE TABLE
testyxp=# CREATE TABLE yxptest_p202201_2 partition of yxptest_p202201 FOR VALUES FROM ('2022-01-10') TO ('2022-01-20');
CREATE TABLE
testyxp=# CREATE TABLE yxptest_p202201_3 partition of yxptest_p202201 FOR VALUES FROM ('2022-01-20') TO ('2022-02-01');
CREATE TABLE
testyxp=# alter table yxptest attach partition yxptest_p202201 for values from ('2010-01-01') to ('2011-01-01');
ALTER TABLE
testyxp=# alter table yxptest DETACH partition yxptest_p202201;
ALTER TABLE
testyxp=# alter table yxptest attach partition yxptest_p202201 for values from ('2022-01-01') TO ('2022-02-01');;
ALTER TABLE
testyxp=# insert into yxptest_p202201 select * from yxptest_p202201_b;
INSERT 0 44640
testyxp=# \d yxptest_p202201
Partitioned table "public.yxptest_p202201"
Column | Type | Collation | Nullable | Default
----------+---------+-----------+----------+---------------------------------------------
id | integer | | not null | nextval('yxptest_p202201_id_seq'::regclass)
peaktemp | integer | | |
logdate | date | | not null |
Partition of: yxptest FOR VALUES FROM ('2022-01-01') TO ('2022-02-01')
Partition key: RANGE (logdate)
Indexes:
"yxptest_p202201_pkey1" PRIMARY KEY, btree (id, logdate)
"yxptest_p202201_peaktemp_idx1" btree (peaktemp)
Number of partitions: 3 (Use \d+ to list them.)
做完操作以后检查索引,发现索引是自动引用父表。
testyxp=# explain select * from yxptest where peaktemp=70552623;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Append (cost=0.29..131.20 rows=24 width=12)
-> Index Scan using yxptest_p202201_1_peaktemp_idx on yxptest_p202201_1 (cost=0.29..8.30 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202201_2_peaktemp_idx on yxptest_p202201_2 (cost=0.29..8.30 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202201_3_peaktemp_idx on yxptest_p202201_3 (cost=0.29..8.30 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202202_peaktemp_idx on yxptest_p202202 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202203_peaktemp_idx on yxptest_p202203 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202204_peaktemp_idx on yxptest_p202204 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202205_peaktemp_idx on yxptest_p202205 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202206_peaktemp_idx on yxptest_p202206 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202207_peaktemp_idx on yxptest_p202207 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202208_peaktemp_idx on yxptest_p202208 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202209_peaktemp_idx on yxptest_p202209 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202210_peaktemp_idx on yxptest_p202210 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202211_peaktemp_idx on yxptest_p202211 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Index Scan using yxptest_p202212_peaktemp_idx on yxptest_p202212 (cost=0.29..8.31 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
-> Bitmap Heap Scan on yxptest_p202301 (cost=4.23..14.79 rows=10 width=12)
Recheck Cond: (peaktemp = 70552623)
-> Bitmap Index Scan on yxptest_p202301_peaktemp_idx (cost=0.00..4.23 rows=10 width=0)
Index Cond: (peaktemp = 70552623)
(33 rows)
testyxp=# explain select * from yxptest where logdate='2022-01-01' and peaktemp=70552623;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Index Scan using yxptest_p202201_1_peaktemp_idx on yxptest_p202201_1 (cost=0.29..8.30 rows=1 width=12)
Index Cond: (peaktemp = 70552623)
Filter: (logdate = '2022-01-01'::date)
(3 rows)
总结:
主键要带上分区键,建组合主键,否则会失败。 不支持在线分区split,就是我们常说的分区表拆分子分区,pg没有类似的功能,但是可以取消挂载的方式重新建立分区再挂到父表。 查询使用分区键,where条件后先写分区键,否则是会查询所有分区,造成不必要的查询成本。

本文作者:叶小普(上海新炬王翦团队)
本文来源:“IT那活儿”公众号
文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
外国CTO也感兴趣的开源数据库项目——openHalo
小满未满、
1814次阅读
2025-04-21 16:58:09
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
381次阅读
2025-04-15 14:48:05
在线重定义——分区表改造
Digital Observer
216次阅读
2025-04-26 21:15:40
转发有奖 | PostgreSQL 16 PGCM高级认证课程直播班招生中!
墨天轮小教习
193次阅读
2025-04-14 15:58:34
中国PostgreSQL培训认证体系新增PGAI应用工程师方向
开源软件联盟PostgreSQL分会
186次阅读
2025-05-06 10:21:13
华象新闻 | PostgreSQL 18 Beta 1、17.5、16.9、15.13、14.18、13.21 发布
严少安
159次阅读
2025-05-09 11:34:10
PG生态赢得资本市场青睐:Databricks收购Neon,Supabase融资两亿美元,微软财报点名PG
老冯云数
148次阅读
2025-05-07 10:06:22
SQL 优化之 OR 子句改写
xiongcc
142次阅读
2025-04-21 00:08:06
告别老旧mysql_fdw,升级正当时
NickYoung
126次阅读
2025-04-29 11:15:18
PostgreSQL中文社区亮相于第八届数字中国峰会
PostgreSQL中文社区
110次阅读
2025-05-07 10:06:20