美文网首页
postgresql分区表

postgresql分区表

作者: 3c9a691b4944 | 来源:发表于2017-12-20 15:06 被阅读17次

原文链接:https://www.bestqliang.com/#/article/13

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

  1. 采用视图分区方式
  2. 采用直接分区方式

创建表

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操作,视图分区不能。

相关文章

  • pg inherit

    借助表的继承特性PostgreSQL实现了分区表功能,虽然相比Oracle、MySQL的分区表来说其实现过程比较麻...

  • PostgreSQL 内置分区

    内置分区表 在 PostgreSQL10 以前,都是通过表的继承和触发器来完成分区功能,在 PostgreSQL1...

  • postgresql分区表

    原文链接:https://www.bestqliang.com/#/article/13 创建自动分区采用两种方式...

  • postgresql实战—分区表

    排它锁(Exclusive locks,X锁):被加锁的对象只能被持有锁的事务读取和修改,其他事务无法在该对象上加...

  • postgresql10以上的自动分区分表功能

    postgresql10以上的自动分区分表功能 一.列分表 1.首先创建主分区表: 这里设置的是根据year列进行...

  • MBR分区与GPT分区

    Linux系统中有两种常见的分区表 MBR分区表(主引导记录分区表)和 GPT分区表(GUID分区表) MBR分区...

  • postgreSQL分区表在rails的应用

    postgerSQL 是通过表继承来实现分区表的。表分区就是把逻辑上的一个大表分割成物理上的几个小块,分区可以提供...

  • Vertica的这些事(九)—— vertica存储统计信息

    vertica存储统计信息: 表数量: 分区表数量: 总表占大小: 分区表总大小: 分区表大小(前10): 分区表...

  • PostgreSQL的分区表插件pg_pathman

    1. 参考资料 参考了前辈们的总结https://yq.aliyun.com/articles/62314http...

  • MySQL-31.分区表

    分区表有什么问题,为什么公司规范不让使用分区表呢? 1.分区表是什么? 为了说明分区表的组织形式,先创建一个表 t...

网友评论

      本文标题:postgresql分区表

      本文链接:https://www.haomeiwen.com/subject/cgiiixtx.html