实例

drop table if exists tab cascade;
CREATE TABLE tab (
id bigint GENERATED ALWAYS AS IDENTITY,
ts timestamp NOT NULL,
data text
);



CREATE or replace FUNCTION part_trig() RETURNS trigger
LANGUAGE plpgsql AS
$$
declare
sql_cmd varchar='';
BEGIN
BEGIN
sql_cmd= format(
'CREATE TABLE %1$s (LIKE tab INCLUDING INDEXES)',
'tab_' || to_char(NEW.ts, 'YYYY_MM_DD')
);
-- raise notice 'sql_cmd=%',sql_cmd;
EXECUTE sql_cmd;
EXECUTE
format(
'NOTIFY tab, %L',
to_char(NEW.ts, 'YYYY-MM-DD')
);
EXCEPTION
WHEN duplicate_table THEN
NULL; -- ignore
END;

EXECUTE
format(
'INSERT INTO %I VALUES ($1.*)',
'tab_' || to_char(NEW.ts, 'YYYY_MM_DD')
)
USING NEW;

RETURN NULL;
END;$$;


CREATE TRIGGER part_trig
BEFORE INSERT ON TAB FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE FUNCTION part_trig();

测试用例

\timing on 
INSERT INTO tab (ts, data)
SELECT clock_timestamp(), 'something'
FROM generate_series(1, 100000);
\dt


ALTER TABLE tab DISABLE TRIGGER part_trig;
truncate tab;
INSERT INTO tab (ts, data)
SELECT clock_timestamp(), 'something'
FROM generate_series(1, 100000);

实操

postgres=# \timing on 
Timing is on.
postgres=# INSERT INTO tab (ts, data)
postgres-# SELECT clock_timestamp(), 'something'
postgres-# FROM generate_series(1, 100000);
\dt


ALTER TABLE tab DISABLE TRIGGER part_trig;
truncate tab;
INSERT INTO tab (ts, data)
SELECT clock_timestamp(), 'something'
FROM generate_series(1, 100000);INSERT 0 0
Time: 4784.318 ms (00:04.784)
postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------+-------+----------
public | tab | table | postgres
public | tab_2022_08_28 | table | postgres
(2 rows)

postgres=#
postgres=#
postgres=# ALTER TABLE tab DISABLE TRIGGER part_trig;
ALTER TABLE
Time: 1.429 ms
postgres=# truncate tab;
TRUNCATE TABLE
Time: 23.540 ms
postgres=# INSERT INTO tab (ts, data)
postgres-# SELECT clock_timestamp(), 'something'
postgres-# FROM generate_series(1, 100000);
INSERT 0 100000
Time: 225.612 ms
postgres=#