带有postgresql-11分区和主键自动递增的问题

问题描述 投票:0回答:1

分区表上的主键增加n(n> 1)而不是1。

试图以多种不同的方式重写plpgsql,但是没有运气。肯定有些东西我听不懂。

CREATE SCHEMA IF NOT EXISTS some_record_pool;

CREATE SEQUENCE some_record_pkey_seq;

create table some_record
(
    id BIGINT not null DEFAULT nextval('some_record_pkey_seq'::regclass),
    device_id bigint,
    device_type bigint,
    record_time timestamp,
    module_serial_number bigint,
    module_id bigint,
    message_type bigint,
    event_code bigint,
    device_status bytea,
    sequence_number bigint,
    data_bytes bigint,
    device_data bytea,
    active boolean,
    deleted boolean,
    created_time timestamp default now() not null,
    created_on timestamp with time zone default now() not null,
    updated_on timestamp with time zone default now() not null
);


CREATE INDEX idx_device_id
    ON public.some_record USING brin
    (device_id)
    TABLESPACE pg_default;

CREATE INDEX idx_module_id
    ON public.some_record USING brin
    (module_id)
    TABLESPACE pg_default;

CREATE INDEX idx_er_created_time
    ON public.some_record (cast(created_time as DATE));

----- CREATE TRIGGER ----------
CREATE OR REPLACE FUNCTION some_record_insert_function()
    RETURNS TRIGGER AS
$$
DECLARE
    partition_date    TEXT;
    partition_name    TEXT;
    start_of_month    TEXT;
    end_of_next_month TEXT;
BEGIN
    partition_date := to_char(NEW.created_time, 'YYYY_MM');
    partition_name := 'some_record_' || partition_date;
    start_of_month := to_char((NEW.created_time), 'YYYY-MM') || '-01';
    end_of_next_month := to_char((NEW.created_time + interval '1 month'), 'YYYY-MM') || '-01';
    IF NOT EXISTS
        (SELECT 1
         FROM information_schema.tables
         WHERE table_name = partition_name)
    THEN
        RAISE NOTICE 'A partition has been created %', partition_name;
        EXECUTE format(
                E'CREATE TABLE some_record_pool.%I ' ||
                E'(CHECK ( date_trunc(\'day\', created_time) >= ''%s'' ' ||
                E'AND date_trunc(\'day\', created_time) < ''%s'')) INHERITS (public.some_record)',
                partition_name, start_of_month, end_of_next_month);
        -- EXECUTE format('GRANT SELECT ON TABLE %I TO readonly',
        -- partition_name); -- use this if you use role based permission
    ELSE
        RAISE NOTICE 'A partition DOES NOT EXIST %', partition_name;
    END IF;
    EXECUTE format(
            'INSERT INTO some_record_pool.%I (device_id, device_type, ' ||
            'record_time, module_serial_number, module_id, message_type, ' ||
            'event_code, device_status, sequence_number, data_bytes, device_data,' ||
            ' active, deleted) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)',
            partition_name) using NEW.device_id, NEW.device_type,
        NEW.record_time, NEW.module_serial_number, NEW.module_id, NEW.message_type,
        NEW.event_code, NEW.device_status, NEW.sequence_number, NEW.data_bytes,
                NEW.device_data, NEW.active, NEW.deleted;
    RETURN NEW;
END
$$
    LANGUAGE plpgsql;


CREATE TRIGGER insert_some_record_trigger
    BEFORE INSERT ON public.some_record
    FOR EACH ROW EXECUTE PROCEDURE public.some_record_insert_function();

--- INSERTING DATA FOR TESTING

INSERT INTO some_record (
    event_record_id, timestamp, event_description_id, event_source_label, event_source_track, event_source_direction, 
    measurement_description, measurement_value, hw_address_module_id, hw_address_rlc_address, sub_system_source, 
    event_type, device_id, active, deleted) VALUES(1, 2, to_timestamp('1953-10-21 14:30:46.555337', 'YYYY-MM-DD HH:MI:SS.US'), 1, 1, 1, 1, NULL, 1, 9, E'9 B
00000000  92 FF 3C 00 7F 00 00 03 E8                         .ÿ<.....è
', TRUE, FALSE, to_timestamp('2019-10-21 14:30:46.555337', 'YYYY-MM-DD HH:MI:SS.US'), to_timestamp('2019-10-21 14:30:46.555337', 'YYYY-MM-DD HH:MI:SS.US'));

代码的重点是自动创建分区并在存在分区的情况下插入数据。

主键应增加一个,但不能这样操作仅一次运行的预期输出是id:1

database-partitioning postgresql-11
1个回答
0
投票

在postgres 12上测试的有效解决方案如下:

/** TABLE PARTITIONING EVENT RECORD **/

-- CREATE PROPER SCHEMA
CREATE SCHEMA IF NOT EXISTS test_par_pool;

-- CREATE PROPER TABLE

CREATE TABLE test_part
(
    id                   bigserial                              not null
        constraint test_part_pkey
            primary key,
    device_id            bigint,
    device_type          bigint,
    record_time          timestamp,
    module_serial_number bigint,
    module_id            bigint,
    message_type         bigint,
    event_code           bigint,
    device_status        bytea,
    sequence_number      bigint,
    data_bytes           bigint,
    device_data          bytea,
    active               boolean,
    deleted              boolean,
    created_time         timestamp                default now() not null,
    created_on           timestamp with time zone default now() not null,
    updated_on           timestamp with time zone default now() not null
);


-- CREATE MINIMAL INDEXES
CREATE INDEX idx_device_id
    ON public.test_part USING brin
    (device_id)
    TABLESPACE pg_default;

CREATE INDEX idx_module_id
    ON public.test_part USING brin
    (module_id)
    TABLESPACE pg_default;

CREATE INDEX idx_er_created_time
    ON public.test_part (cast(created_time as DATE));

-- CREATE INSERT FUNCTIONS

CREATE OR REPLACE FUNCTION test_par_insert_function()
    RETURNS TRIGGER AS
$$
DECLARE
    partition_date    TEXT;
    partition         TEXT;
    start_of_month    TEXT;
    end_of_next_month TEXT;
    stmt              TEXT;
BEGIN
    partition_date := to_char(NEW.created_time, 'YYYY_MM');
    partition := TG_RELNAME || '_' || partition_date;
    start_of_month := to_char((NEW.created_time), 'YYYY-MM') || '-01';
    end_of_next_month := to_char((NEW.created_time + interval '1 month'), 'YYYY-MM') || '-01';
    IF NOT EXISTS(SELECT relname FROM pg_class WHERE relname = partition) THEN
        RAISE NOTICE 'A partition has been created %',partition;
        stmt = 'CREATE TABLE test_par_pool.' || partition || ' (check (date_trunc(''day'', created_time) >= '
                   || chr(39) || start_of_month || chr(39)
                   || ' AND date_trunc(''day'', created_time) < '
                   || chr(39) || end_of_next_month
                   || chr(39) || ' )) INHERITS ( public.' || TG_RELNAME ||
               ');';
        EXECUTE stmt;
    END IF;
    EXECUTE 'INSERT INTO test_par_pool.' || partition ||
            ' SELECT( public.' || TG_RELNAME || ' ' || quote_literal(NEW) || ').* RETURNING id;';
    RETURN NULL;

END
$$
    LANGUAGE plpgsql;

-- CREATE TRIGGER

CREATE TRIGGER insert_test_part_trigger
    BEFORE INSERT ON public.test_part
    FOR EACH ROW EXECUTE PROCEDURE public.test_par_insert_function();
© www.soinside.com 2019 - 2024. All rights reserved.