• Postgresql分表与优化


    --1、创建主表
    CREATE TABLE tbl_partition
    (
      date_key date,
      hour_key smallint,
      client_key integer,
      item_key integer,
      account integer,
      expense numeric
    );
    
    --2、创建多个分表。每个分区表必须继承自主表,并且正常情况下都不要为这些分区表添加任何新的列。
    CREATE TABLE tbl_partition_2016_01() inherits (tbl_partition);
    CREATE TABLE tbl_partition_2016_02() inherits (tbl_partition);
    CREATE TABLE tbl_partition_2016_03() inherits (tbl_partition);
    --CREATE TABLE tbl_partition_2016_04() inherits (tbl_partition);
    
    --3、TODO为分区表添加限制。这些限制决定了该表所能允许保存的数据集范围。这里必须保证各个分区表之间的限制不能有重叠。
    ALTER TABLE tbl_partition_2016_01
    ADD CONSTRAINT tbl_partition_2016_01_check_date_key
    CHECK (date_Key >= '2016-01-01'::date AND date_Key < '2016-02-01'::date);
    ALTER TABLE tbl_partition_2016_02
    ADD CONSTRAINT tbl_partition_2016_02_check_date_key
    CHECK (date_Key >= '2016-02-01'::date AND date_Key < '2016-03-01'::date);
    ALTER TABLE tbl_partition_2016_03
    ADD CONSTRAINT tbl_partition_2016_03_check_date_key
    CHECK (date_Key >= '2016-03-01'::date AND date_Key < '2016-04-01'::date);
    
    --4、为每一个分区表,在主要的列上创建索引。该索引并不是严格必须创建的,但在大部分场景下,它都非常有用。
    ---CREATE INDEX tbl_partition_all_date_key ON tbl_partition_all (date_key,client_key);
    CREATE INDEX tbl_partition_date_key_2016_01
    ON tbl_partition_2016_01 (date_key,client_key);
    CREATE INDEX tbl_partition_date_key_2016_02
    ON tbl_partition_2016_02 (date_key,client_key);
    CREATE INDEX tbl_partition_date_key_2016_03
    ON tbl_partition_2016_03 (date_key,client_key);
    
    --5、定义一个trigger或者rule把对主表的数据插入操作重定向到对应的分区表。
    --创建分区函数
    CREATE OR REPLACE FUNCTION tbl_partition_trigger()
      RETURNS TRIGGER AS $$
    BEGIN
      IF NEW.date_key >= DATE '2016-01-01' AND NEW.date_Key < DATE '2016-02-01'
      THEN
        INSERT INTO tbl_partition_2016_01 VALUES (NEW.*);
      ELSIF NEW.date_key >= DATE '2016-02-01' AND NEW.date_Key < DATE '2016-03-01'
        THEN
          INSERT INTO tbl_partition_2016_02 VALUES (NEW.*);
      ELSIF NEW.date_key >= DATE '2016-03-01' AND NEW.date_Key < DATE '2016-04-01'
        THEN
          INSERT INTO tbl_partition_2016_03 VALUES (NEW.*);
      END IF;
      RETURN NULL;
    END;
    $$
    LANGUAGE plpgsql;
    
    --6、挂载分区Trigger
    CREATE TRIGGER insert_tbl_partition_trigger
    BEFORE INSERT ON tbl_partition
    FOR EACH ROW EXECUTE PROCEDURE tbl_partition_trigger();
    
    --7、创建全表
    CREATE TABLE tbl_partition_all
    (
      date_key date,
      hour_key smallint,
      client_key integer,
      item_key integer,
      account integer,
      expense numeric
    );
    
    --8、自动建表触发器
    CREATE OR REPLACE FUNCTION tbl_partition_trigger()
      RETURNS TRIGGER AS $$
    DECLARE month_text TEXT;
            this_month_first_day_text TEXT;
            next_month_first_day_text TEXT;
            insert_statement TEXT;
    BEGIN
      SELECT to_char(NEW.date_key, 'YYYY_MM') INTO month_text;
      SELECT get_month_first_day(NEW.date_key) INTO this_month_first_day_text;
      SELECT to_char(to_date(this_month_first_day_text,'YYYY-MM-DD') + interval '1 month', 'YYYY-MM-DD') INTO next_month_first_day_text;
      insert_statement := 'INSERT INTO tbl_partition_'
                          || month_text||' VALUES ($1.*)';
      EXECUTE insert_statement USING NEW;
      RETURN NULL;
      EXCEPTION
      WHEN UNDEFINED_TABLE
        THEN
          EXECUTE
          'CREATE TABLE IF NOT EXISTS tbl_partition_'
          || month_text
          || '(CHECK (date_key >= '''
          || this_month_first_day_text
          || ''' and date_key<'''
          || next_month_first_day_text
          || ''')) INHERITS (tbl_partition)';
          RAISE NOTICE 'CREATE NON-EXISTANT TABLE tbl_partition_%', month_text;
          EXECUTE
          'CREATE INDEX tbl_partition_date_key_'
          || month_text
          || ' ON tbl_partition_'
          || month_text
          || '(date_key)';
          EXECUTE insert_statement USING NEW;
          RETURN NULL;
    END;
    $$
    LANGUAGE plpgsql;
    
    --get_month_first_day
    CREATE OR REPLACE FUNCTION get_month_first_day(in in_date date,out out_date text)
    AS $$
    BEGIN
      SELECT to_char(in_date, 'YYYY_MM')||'_01' INTO out_date;
    END;
    $$
    LANGUAGE plpgsql;
    
    --插入数据脚本
    INSERT INTO
        tbl_partition_all
    select
        (select
            array_agg(i::date)
        from
            generate_series(
            '2015-12-01'::date,
            '2015-12-30'::date,
            '1 day'::interval) as t(i)
        )[floor(random()*4)+1] as date_key,
        floor(random()*24) as hour_key,
        floor(random()*1000000)+1 as client_key,
        floor(random()*100000)+1 as item_key,
        floor(random()*20)+1 as account,
        floor(random()*10000)+1 as expense
    from
        generate_series(1,300000000,1);
        
    INSERT INTO tbl_partition SELECT * FROM tbl_partition_all;
    
    
    -------------------------------------------------主体结束-----------------------------------------
    -------------------------------------------------主体结束-----------------------------------------
    
    --使用rule创建分表
    CREATE RULE tbl_partition_rule_2016_01 AS
    ON INSERT TO tbl_partition
      WHERE
        date_key >= DATE '2016-01-01' AND date_Key < DATE '2016-02-01'
    DO INSTEAD
      INSERT INTO tbl_partition_2016_01 VALUES (NEW.*);
    
    --删除继承关系
    ALTER TABLE tbl_partition_2016_01 NO INHERIT tbl_partition;
    
    --查询对比测试
    EXPLAIN  ANALYZE
    select count(account) ,client_key  from  tbl_partition  v
    where v.date_key >='2016-03-02'   and v.date_key <='2016-03-07' group by client_key ;
    
    EXPLAIN  ANALYZE
    select count(account) ,client_key  from  tbl_partition_all  v
    where v.date_key >='2016-03-02'   and v.date_key <='2016-03-12' group by client_key ;
  • 相关阅读:
    HotSpot 虚拟机垃圾回收算法实现
    多线程死锁的产生原因以及如何避免
    Java异常实战——OutOfMemoryError
    MySQL数据库中的四种隔离级别
    Java运行时数据区概述
    MySQL 字符集和校对
    debezium关于cdc的使用(下)
    debezium关于cdc的使用(上)
    对xxl-job进行simpleTrigger并动态创建任务扩展
    折腾Java设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/winkey4986/p/6824747.html
Copyright © 2020-2023  润新知