把一个大的物理表分成若干个小物理表,并使得这些小物理表在逻辑上可以被当成一张表来使用。
主表是创建子表的模板,是一个正常的普通表,一般主表并不存任何数据。
子表继承并属于一个主表,与主表是一对多的关系,子表中存储所有的数据
• 配置表:数据量小,易管理与优化
• 状态表:数据量大,性能问题
• 流水表:有明显的时间变化,每天数据量都很大,定期归档
• 统计表:加载后数据不变,数据量很大,需统计分析
主表和分区表需分别创建,各自定义,数据不能自动关联
主表和分区表关系:通过继承和触发器实现
创建步骤:
CREATE TABLE pg_9_tab( id serial,uid int4,username varchar,create_time bigint);
CREATE INDEX idx_pg_9_tab_ctime ON pg_9_tab USING btree (create_time);
CREATE TABLE pg_9_tab_p_hisotry(CHECK ( create_time < 1569859200 ) ) INHERITS(pg_9_tab);
CREATE TABLE pg_9_tab_p_201910(CHECK ( create_time >= 1569859200 and create_time < 1572537600 ) ) INHERITS(pg_9_tab);
CREATE TABLE pg_9_tab_p_201911(CHECK ( create_time >= 1572537600 and create_time < 1575129600 ) ) INHERITS(pg_9_tab);
CREATE TABLE pg_9_tab_p_201912(CHECK ( create_time >= 1575129600 and create_time < 1577808000 ) ) INHERITS(pg_9_tab);
CREATE INDEX idx_pg_9_tab_p_hisotry_ctime ON pg_9_tab_p_hisotry USING btree (create_time);
CREATE INDEX idx_pg_9_tab_p_201910_ctime ON pg_9_tab_p_201910 USING btree (create_time);
CREATE INDEX idx_pg_9_tab_p_201911_ctime ON pg_9_tab_p_201911 USING btree (create_time);
CREATE INDEX idx_pg_9_tab_p_201912_ctime ON pg_9_tab_p_201912 USING btree (create_time);
CREATE OR REPLACE FUNCTION pg_9_tab_insert_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
… …
END;
$function$;
CREATE TRIGGER insert_pg_9_tab_trigger BEFORE INSERT ON pg_9_tab FOR EACH ROW EXECUTE PROCEDURE pg_9_tab_insert_trigger();
set constraint_exclusion = partition;
show constraint_exclusion;
Postgresql 10提供了内置分区表,不需要预先在父表上定义触发器,对父表的DML操作也会自动路由到相应分区。
仅支持范围分区和列表分区。
创建步骤:
CREATE TABLE pg_10_tab( id serial, uid int4, username varchar, create_time bigint ) PARTITION BY RANGE(create_time);
CREATE TABLE pg_10_tab_p_hisotry PARTITION OF pg_10_tab FOR VAlUES FROM (1546272000) TO (1569859200);
CREATE TABLE pg_10_tab_p_201910 PARTITION OF pg_10_tab FOR VAlUES FROM (1569859200) TO (1572537600);
CREATE TABLE pg_10_tab_p_201911 PARTITION OF pg_10_tab FOR VAlUES FROM (1572537600) TO (1575129600);
CREATE TABLE pg_10_tab_p_201912 PARTITION OF pg_10_tab FOR VAlUES FROM (1575129600) TO (1577808000);
CREATE INDEX idx_pg_10_tab_p_hisotry_ctime ON pg_10_tab_p_hisotry USING btree (create_time);
CREATE INDEX idx_pg_10_tab_p_201910_ctime ON pg_10_tab_p_201910 USING btree (create_time);
CREATE INDEX idx_pg_10_tab_p_201911_ctime ON pg_10_tab_p_201911 USING btree (create_time);
CREATE INDEX idx_pg_10_tab_p_201912_ctime ON pg_10_tab_p_201912 USING btree (create_time);
INSERT INTO pg_10_tab(uid,username,create_time) SELECT round(1000*random()),chr(int4(random()*26)+65),generate_series(1568476800,1576339200,360);
SELECT count(*) FROM pg_10_tab;
SELECT count(*) FROM ONLY pg_10_tab;
\dt+ pg_10_tab*
功能增强:
性能方面:
创建步骤:
CREATE TABLE pg_11_tab( id serial, uid int4, username varchar, create_time bigint ) PARTITION BY RANGE(create_time);
CREATE INDEX idx_pg_11_tab_ctime ON pg_11_tab USING btree (create_time);
CREATE TABLE pg_11_tab_p_hisotry PARTITION OF pg_11_tab DEFAULT;
CREATE TABLE pg_11_tab_p_201910 PARTITION OF pg_11_tab FOR VAlUES FROM (1569859200) TO (1572537600);
CREATE TABLE pg_11_tab_p_201911 PARTITION OF pg_11_tab FOR VAlUES FROM (1572537600) TO (1575129600);
CREATE TABLE pg_11_tab_p_201912 PARTITION OF pg_11_tab FOR VAlUES FROM (1575129600) TO (1577808000);
CREATE INDEX idx_pg_11_tab_p_hisotry_ctime ON pg_11_tab_p_hisotry USING btree (create_time); ##不用执行
CREATE INDEX idx_pg_11_tab_p_201910_ctime ON pg_11_tab_p_201910 USING btree (create_time);
CREATE INDEX idx_pg_11_tab_p_201911_ctime ON pg_11_tab_p_201911 USING btree (create_time);
CREATE INDEX idx_pg_11_tab_p_201912_ctime ON pg_11_tab_p_201912 USING btree (create_time); ##不用执行
INSERT INTO pg_11_tab(uid,username,create_time) SELECT round(1000*random()),chr(int4(random()*26)+65),generate_series( 1568476800, 1576339200, 360);
SELECT count(*) FROM pg_11_tab;
SELECT count(*) FROM ONLY pg_11_tab;
\dt+ pg_11_tab*
创建步骤:
CREATE TABLE pg_12_tab( id serial, uid int4, username varchar, create_time bigint ) PARTITION BY RANGE(create_time);
CREATE INDEX idx_pg_12_tab_ctime ON pg_11_tab USING btree (create_time);
CREATE TABLE pg_12_tab_p_hisotry PARTITION OF pg_12_tab DEFAULT;
CREATE TABLE pg_12_tab_p_201910 PARTITION OF pg_12_tab FOR VAlUES FROM (1569859200) TO (1572537600);
CREATE TABLE pg_12_tab_p_201911 PARTITION OF pg_12_tab FOR VAlUES FROM (1572537600) TO (1575129600);
CREATE TABLE pg_12_tab_p_201912 PARTITION OF pg_12_tab FOR VAlUES FROM (1575129600) TO (1577808000);
INSERT INTO pg_12_tab(uid,username,create_time)
SELECT round(1000*random()),chr(int4(random()*26)+65),generate_series( 1568476800, 1576339200, 360);
SELECT count(*) FROM pg_12_tab;
SELECT count(*) FROM ONLY pg_12_tab;
\dt+ pg_12_tab*
table
.*
) to be used in partitioning expressions (Amit Langote)案例参考: https://mp.weixin.qq.com/s/MbkdarHRrVGm3faiN7SOpw
PostgreSQL: Documentation: 13: E.5. Release 13
更新和删除可以定位到更精细的分区,性能提高,节省内存
Autovacuum现在支持analyze分区表,并将行统计信息反馈到父表,另外可以通过调整maintenance_io_concurrency异步IO参数调优。
支持非阻塞的ALTER TABLE ... DETACH PARTITION ... CONCURRENTLY
所有分区子表支持 reindex,pg 14还新增了pg_amcheck工具用于检查数据是否损坏
参考
《斗鱼 PostgreSQL分区表实践与思考_zhaofx_v1.5_20191122》
PostgreSQL表分区演进
关于分区表的方方面面