如何使用bigint列在postgres中创建动态分区表?

时间:2018-04-09 09:11:52

标签: sql postgresql plpgsql database-partitioning

我有一个主表,例如

CREATE TABLE public.user_event_firebase
(
    user_id character varying(32) COLLATE pg_catalog."default" NOT NULL,
    event_name character varying(255) COLLATE pg_catalog."default" NOT NULL,
    "timestamp" bigint NOT NULL,
    platform character varying(255) COLLATE pg_catalog."default" NOT NULL,
    created_at timestamp without time zone DEFAULT now()
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

目标

我想通过year_month表将此表分区为“ timestamp ”列,例如user_event_firebase_2018_04,user_event_firebase_2018_05,user_event_firebase_2018_06。行将自动重定向以插入具有时间戳条件的分区表。

我创建了功能创建分区,例如:

CREATE OR REPLACE FUNCTION partition_uef_table( bigint, bigint )
returns void AS $$
DECLARE
    create_query text;
    index_query text;
BEGIN
    FOR create_query, index_query IN SELECT
            'create table user_event_firebase_'
            || TO_CHAR( d, 'YYYY_MM' )
            || ' ( check( timestamp >= bigint '''
            || TO_CHAR( d, 'YYYY-MM-DD' )
            || ''' and timestamp < bigint '''
            || TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD' )
            || ''' ) ) inherits ( user_event_firebase );',
            'create index user_event_firebase_'
            || TO_CHAR( d, 'YYYY_MM' )
            || '_time on user_event_firebase_' 
            || TO_CHAR( d, 'YYYY_MM' )
            || ' ( timestamp );'
        FROM generate_series( $1, $2, '1 month' ) AS d
    LOOP
        EXECUTE create_query;
        EXECUTE index_query;
    END LOOP;
END;
$$
language plpgsql;

CREATE OR REPLACE FUNCTION test_partition_function_uef()
RETURNS TRIGGER AS $$
BEGIN
    EXECUTE 'insert into user_event_firebase_'
        || to_char( NEW.timestamp, 'YYYY_MM' )
        || ' values ( $1, $2, $3, $4 )' USING NEW.user_id, NEW.event_name, NEW.timestamp, NEW.platform;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

带触发器

CREATE TRIGGER test_partition_trigger_uef
    BEFORE INSERT
    ON user_event_firebase
    FOR each ROW
    EXECUTE PROCEDURE test_partition_function_uef() ;

我尝试使用示例

SELECT partition_uef_table(1518164237,1520583437) ;

问题:

ERROR:  invalid input syntax for integer: "1 month"
LINE 14:   FROM generate_series( $1, $2, '1 month' ) AS d
                                         ^
QUERY:  SELECT
            'create table user_event_firebase_'
            || TO_CHAR( d, 'YYYY_MM' )
            || ' ( check( timestamp >= bigint '''
            || TO_CHAR( d, 'YYYY-MM-DD' )
            || ''' and timestamp < bigint '''
            || TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD' )
            || ''' ) ) inherits ( user_event_firebase );',
            'create index user_event_firebase_'

问题:

如何在'1个月'中为generate_series函数创建范围,将step属性设置为int或bigint suck,因为每月的日期是不同的(第2天 - 第28天,第3天 - 第30天)。

谢谢。

1 个答案:

答案 0 :(得分:1)

回答你的第二个问题是基于意见(所以我跳过它),但对第一个问题是这样的:

products

给予了回报:

with args(a1,a2) as (values(1518164237,1520583437))
select d,to_char(d,'YYYY_MM') from args, generate_series(to_timestamp(a1),to_timestamp(a2),'1 month'::interval) d;

Use

  

generate_series(开始,停止,步骤间隔)时间戳或带时区的时间戳