数据库按月分表

当业务中涉及到告警信息存储时,我们会因为数据量过大而必须进行分表操作。例如实际工作中遇到的接收并存储告警,对于普遍的业务场景而言,一天产生的告警数量往往是以千条甚至万条为单位,这种情况下如果用一张表存储,可能过上几个月这张表就很难支撑基本的查询操作,可能会影响组件效率。

数据库分表的意义

(1)分表,从字面上理解就是将原本存储在一张表上面的数据,分块存储到多个表上这样做的好处显而易见就是突破了CPU、磁盘、内存等资源的瓶颈。

数据库分表方式

(1)垂直分表

所谓的垂直分表指的是将表结构按照功能模块、关系密切程度划分出来,部署到不同的库或者不同的表中。其实就是数据库设计所要遵循的范式原则。尽量减少表之间的耦合,避免存储过多的冗余数据。

(2)水平分表

所谓的水平分表,即将表按照某种规则,例如告警表,可以使用按月或者按天分表,即每个月的告警数据单独存储在一张表中。这些表同时属于一张主表,拥有相同的表结构,但查询时可以大大减轻主表查询的负担。

实际代码

咱们说点实际的,以下是我在做定时项目时用到的告警表按月分表方案,方案流程:为告警表设置触发器,当添加告警数据时,自动判断告警中的“告警发生时间”字段,根据时间按月分表。

DROP FUNCTION IF EXISTS "public"."auto_insert_into_library_details"();

CREATE OR REPLACE FUNCTION "public"."auto_insert_into_library_details"()

  RETURNS "pg_catalog"."trigger" AS $BODY$

DECLARE

    time_column_name    text ;          -- 父表中用于分区的时间字段的名称[必须首先初始化!!]

    curMM       varchar(8);     -- 'YYYYMM'字串,用做分区子表的后缀

    isExist         boolean;        -- 分区子表,是否已存在

    startTime       text;

    endTime     text;

    strSQL          text;

 

BEGIN

    -- 调用前,必须首先初始化(时间字段名):time_column_name [直接从调用参数中获取!!]

    time_column_name := TG_ARGV[0];

 

    -- 判断对应分区表 是否已经存在?

    EXECUTE 'SELECT $1.'||time_column_name INTO strSQL USING NEW;

    curMM := to_char( strSQL::timestamp , 'YYYYMM' );

    select count(*) INTO isExist from pg_class where relname = (TG_RELNAME||'_'||curMM);

 

    -- 若不存在, 则插入前需 先创建子分区

    IF ( isExist = false ) THEN

        -- 创建子分区表

        startTime := curMM||'01 00:00:00.000';

        endTime := to_char( startTime::timestamp + interval '1 month''YYYY-MM-DD HH24:MI:SS.MS');

        strSQL := 'CREATE TABLE IF NOT EXISTS '||TG_RELNAME||'_'||curMM||

                  ' ( CHECK('||time_column_name||'>='''|| startTime ||''' AND '

                             ||time_column_name||'< '''|| endTime ||''' )

                          ) INHERITS ('||TG_RELNAME||') ;'  ;

        EXECUTE strSQL;

 

        -- 创建索引

        strSQL := 'CREATE INDEX '||TG_RELNAME||'_'||curMM||'_INDEX_'||time_column_name||' ON '

                  ||TG_RELNAME||'_'||curMM||' ('||time_column_name||');' ;

        EXECUTE strSQL;

 

    END IF;

 

    -- 插入数据到子分区!

    strSQL := 'INSERT INTO '||TG_RELNAME||'_'||curMM||' SELECT $1.*' ;

    EXECUTE strSQL USING NEW;

    RETURN NULL;

END

分表还有啥

这里只是简单的分享了一下之前用到的分表语句,实际上分表的好处远不止分散存储数据这么简单,例如数据库分库分表涉及的读写分离,以及如何保持数据一致性等问题还有待深入了解,这个等笔者以后慢慢学习再分享吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值