当业务中涉及到告警信息存储时,我们会因为数据量过大而必须进行分表操作。例如实际工作中遇到的接收并存储告警,对于普遍的业务场景而言,一天产生的告警数量往往是以千条甚至万条为单位,这种情况下如果用一张表存储,可能过上几个月这张表就很难支撑基本的查询操作,可能会影响组件效率。
数据库分表的意义
(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 |
分表还有啥
这里只是简单的分享了一下之前用到的分表语句,实际上分表的好处远不止分散存储数据这么简单,例如数据库分库分表涉及的读写分离,以及如何保持数据一致性等问题还有待深入了解,这个等笔者以后慢慢学习再分享吧