资讯专栏INFORMATION COLUMN

postgresql分区表

EdwardUp / 826人阅读

摘要:创建自动分区采用两种方式采用视图分区方式采用直接分区方式创建表创建索引采用视图分区方式建立视图定义分表保证分区后的可以自增按照时间进行分区分表触发器定义更新更新触发器直接分区方式分表触发器两种方式比较视图分区所有操作都是对视图的操

创建自动分区采用两种方式

采用视图分区方式

采用直接分区方式

创建表
CREATE TABLE IF NOT EXISTS public.sales
(
    id bigserial primary key ,
    store_id varchar(50) ,
    business_date date,
    start_time time,
    end_time time,
    dine_in_tc int,
    delivery_tc int,
    takeout_tc int,
    dine_in_s decimal(20,4),
    delivery_s decimal(20,4),
    takeout_s decimal(20,4),
    voucher_overcharge decimal(20,4),
    freight decimal(20,4),
    currency varchar(16),
    created_at timestamp default now(),
    updated_at timestamp default now()
);
创建索引
CREATE INDEX sales_store_id ON public.sales (store_id);
CREATE INDEX sales_business_date ON public.sales (business_date);
ALTER TABLE public.sales  ADD CONSTRAINT sales_storeid_businessdate_starttime_endtime UNIQUE(store_id,business_date,start_time,end_time);
1.采用视图分区方式 建立视图
CREATE VIEW public.sales_view AS SELECT * FROM public.sales;
定义分表function
CREATE OR REPLACE FUNCTION public.insert_sales() 
RETURNS TRIGGER AS
"."$BODY"."$
DECLARE
    _start_dt text;
    _end_dt text;
    _table_name text;
BEGIN     
IF NEW.id IS NULL THEN
NEW.id := nextval("sales_id_seq");    // 保证分区后的id可以自增
END IF;
_table_name := "sales_view_" || to_char(NEW.business_date, "YYYY_MM");    // 按照时间进行分区

PERFORM 1
FROM   pg_catalog.pg_class c
JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relkind = "r"
AND    c.relname = _table_name
AND    n.nspname = public;
IF NOT FOUND THEN
    _start_dt := to_char(date_trunc("month", NEW.business_date), "YYYY-MM-DD");
    _end_dt:=_start_dt::timestamp + INTERVAL "1 month";
    EXECUTE 
    "CREATE TABLE public." 
    || quote_ident(_table_name) 
    || " (CHECK (business_date >= " 
    || quote_literal(_start_dt) 
    || "AND business_date < " 
    || quote_literal(_end_dt) 
    || ")) INHERITS (public.sales)";
    EXECUTE "CREATE INDEX " || quote_ident(_table_name||"_business_date"||_start_dt) || " ON public." || quote_ident(_table_name) || " (business_date)";
    EXECUTE "CREATE INDEX " || quote_ident(_table_name||"_store_id"||_start_dt) || " ON public." || quote_ident(_table_name) || " (store_id)";
    EXECUTE "ALTER TABLE public." || quote_ident(_table_name) || " ADD CONSTRAINT " || quote_ident(_table_name||"_storeid_businessdate_starttime_endtime"||_start_dt) || " UNIQUE (store_id,business_date,start_time,end_time)";
    EXECUTE "ALTER TABLE public." || quote_ident(_table_name) || " OWNER TO " || quote_ident(current_user);
    EXECUTE "GRANT ALL ON TABLE public." || quote_ident(_table_name) || " TO " || quote_ident(current_user);
END IF;
    EXECUTE "INSERT INTO public." || quote_ident(_table_name) || " VALUES ($1.*) RETURNING *" USING NEW;
    RETURN NEW;
END;
"."$BODY"."$
LANGUAGE plpgsql;
";
分表触发器
CREATE TRIGGER insert_sales_trigger INSTEAD OF INSERT ON public.sales_view FOR EACH ROW EXECUTE PROCEDURE insert_sales();
定义更新function
CREATE OR REPLACE FUNCTION update_sales()
RETURNS TRIGGER AS $$
BEGIN
    DELETE FROM sales_view WHERE id = NEW.id;
    INSERT INTO sales_view VALUES (NEW.*);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
";
更新触发器
CREATE TRIGGER update_sales_trigger INSTEAD OF UPDATE ON sales_view FOR EACH ROW EXECUTE PROCEDURE update_oc_sales();
2.直接分区方式
CREATE OR REPLACE FUNCTION insert_sales() 
RETURNS TRIGGER AS
"."$BODY"."$
DECLARE
    _start_dt text;
    _end_dt text;
    _table_name text;
BEGIN     
IF NEW.id IS NULL THEN
    NEW.id := nextval("".$this->tableName."_id_seq");  
END IF;
_table_name := "sales_" || to_char(NEW.business_date, "YYYY_MM");
PERFORM 1
FROM   pg_catalog.pg_class c
JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relkind = "r"
AND    c.relname = _table_name
AND    n.nspname = "public";
IF NOT FOUND THEN
    _start_dt := to_char(date_trunc("month", NEW.business_date), "YYYY-MM-DD");
    _end_dt:=_start_dt::timestamp + INTERVAL "1 month";
    EXECUTE 
    "CREATE TABLE IF NOT EXISTS public." 
    || quote_ident(_table_name) 
    || " (CHECK (business_date >= " 
    || quote_literal(_start_dt) 
    || "AND business_date < " 
    || quote_literal(_end_dt) 
    || ")) INHERITS (public.sales)";
    EXECUTE "CREATE INDEX IF NOT EXISTS" || quote_ident(_table_name||"_business_date"||_start_dt) || " ON public." || quote_ident(_table_name) || " (business_date)";
    EXECUTE "CREATE INDEX IF NOT EXISTS" || quote_ident(_table_name||"_store_id"||_start_dt) || " ON public." || quote_ident(_table_name) || " (store_id)";
    EXECUTE "CREATE UNIQUE INDEX IF NOT EXISTS" || quote_ident(_table_name||"_storeid_businessdate_starttime_endtime"||_start_dt) || " ON public." || quote_ident(_table_name) || " (store_id,business_date,start_time,end_time)";
    EXECUTE "ALTER TABLE public." || quote_ident(_table_name) || " OWNER TO " || quote_ident(current_user);
    EXECUTE "GRANT ALL ON TABLE public." || quote_ident(_table_name) || " TO " || quote_ident(current_user);
END IF;
    EXECUTE "INSERT INTO public." || quote_ident(_table_name) || " VALUES ($1.*) on conflict(store_id,business_date,start_time,end_time) do nothing RETURNING *" USING NEW;
    RETURN NULL;
END;
"."$BODY"."$
LANGUAGE plpgsql;
分表触发器
CREATE TRIGGER insert_sales_trigger BEFORE INSERT ON public.salses FOR EACH ROW EXECUTE PROCEDURE insert_sales();

两种方式比较

视图分区所有操作都是对视图的操作,直接分区是对主表进行操作;

视图分区触发器使用instead of,直接分区使用before,因为无法直接用触发器替代对主表的操作,只能操作视图;

视图分区用instead of,在function中可以RETURN NEW,对数据库操作后有明确的返回,直接分区用before方式,在function中采用RETURN NULL,数据库操作没有返回;

直接分区可以用on conflict对主表insert进行ignore操作,视图分区不能。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38984.html

相关文章

  • 新书推荐 |《PostgreSQL实战》出版(提供样章下载)

    摘要:作者谭峰张文升出版日期年月页数页定价元本书特色中国开源软件推进联盟分会特聘专家撰写,国内多位开源数据库专家鼎力推荐。张文升中国开源软件推进联盟分会核心成员之一。 很高兴《PostgreSQL实战》一书终于出版,本书大体上系统总结了笔者 PostgreSQL DBA 职业生涯的经验总结,本书的另一位作者张文升拥有丰富的PostgreSQL运维经验,目前就职于探探科技任首席PostgreS...

    Martin91 评论0 收藏0
  • PostgreSQL 自动分区分表维护管理插件 pathman 基础使用

    摘要:使用数据库会自动的根据从某几个片中读取数据。更加详细的请参考德哥文章 官方地址:https://github.com/postgrespr...关于pathman的原理和优化问题,请移步至https://yq.aliyun.com/article... 检查环境变量如果直接执行psql命令提示command not found则执行下面的命令设置环境变量 root@host# PA...

    MASAILA 评论0 收藏0
  • 构建可扩展的PostgreSQL解决方案

    摘要:这可以通过负载平衡来实现数据分片当问题不是并发查询的数量,而是数据库的大小和单个查询的速度时,可以实现不同的方法。 showImg(https://segmentfault.com/img/remote/1460000018875091); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slogan | 连接每个程序员的故事 网站 | http://chaindesk.cn...

    jonh_felix 评论0 收藏0
  • 构建可扩展的PostgreSQL解决方案

    摘要:这可以通过负载平衡来实现数据分片当问题不是并发查询的数量,而是数据库的大小和单个查询的速度时,可以实现不同的方法。 showImg(https://segmentfault.com/img/remote/1460000018875091); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slogan | 连接每个程序员的故事 网站 | http://chaindesk.cn...

    FrozenMap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<