• 谈谈数据库中的水平分库分表的使用场景
  • 发布于 2个月前
  • 221 热度
    0 评论
  • 汤彬
  • 3 粉丝 10 篇博客
  •   
分库分表,顾名思义,分库分表就是按照一定的规则,对原有的数据库和表进行拆分,把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。一般用到的分表分表技术有水平切割和垂直切割技术。

为什么要分库分表呢?说海量数据有点夸张了,反正数据增长比较快,数据库里的数据暴涨。时间一长数据库根本承受不住。

垂直分库/表一般就是例如把一个班级的课程 ID、学生学号等信息单独隔离到一个数据库上,优点在于拆分切割后业务专用、专用专用。缺点在于不支持跨库 join 链接关联查询。

水平分库/表就是比如一个表中存在一个字段存的时间,类型为 timestamp。会根据年月日来切割成多个表。比如有个表  test。那么它会切割成很多个这样的表,但是在分区后的表在进行这样的统计时是需要进行动大手术的。

比如形成test_20181126、 test_20181127、test_20181128等,这些切割后的表的结构是一模一样的。只不过把数据分开放了,每一天单独的放在一个表里面。

今天来重点说一下,水平分库/表后的场景

如上所说,当去统计一段时间内dbtest这张表的业务数据,要求汇总时,就是一个大的麻烦事。一般大公司都会遇到或者碰到这种场景。比如应用系统报表统计需要、再比如应用系统相关查询统计等需要。这样的需求太多了太多了。比如我刚毕业时候做的 HIS 系统。医院的收费处和挂号处就需要去统计今天挂了多少个号、有多少个人收费了、以及在一天的某个时间段内的挂号总金额和处方收费总金额等。

第一种一般是人工手写 SQL 语句运用  UNION ALL  去关联汇总。但是这种方法太耗时间、很费人力、很费眼力。每一天都会有一个新表,比如现在统计前10天到今天的数据,那就需要10端 UNION ALL拼接,比如到了明天呢? 又得加一段。这还好,比如 100 天呢? 365 天呢? 明显不会是 365 段 UNION ALL。这不把人累死。所以一般这种方案适合统计短时间内的业务数据。比如dbtest中有a、b、c三个字段。select a、b、c  from test_20181126,在UNION ALL 去关联select a、b、c  from test_20181127 这得弄到啥时候去。

第二种就是用存过过程配合中间表去实现。存储过程自动循环。建立临时中间表运用动态 SQL 申明游标。临时表的表结构和业务分区表的表结构是一模一样的。当然和中间表的结构也是一样的。存储过程一般都是放在二半夜去执行的。每一天都会选取一个定时的点去执行,但是这类业务场景一般都是第二天去拿头一天的数据。

这类方案也有它的弊端。但是很多公司都会折中选择这种方案。弊端到底是什么呢? 时间一长,中间表中的数据会很大,从分区表拿来的数据一直往这里面存放,水满则溢。所以,数据量一大,查询避免不了会变慢、就算加索引强制走索引亦或者是优化 SQL 写法都未必见得能有多快得了。

那么这时候有人就在想了,那高哥,要按照你这么说那这系统还有办法做吗? 方案当然有,更好的方案就是需要后端在写 SQL 时注意写法以及需要 DBA 去配合改善优化及分表时如无必要去按照天分,可以按照周或者月去分。退一步讲,就算实在是按照天来分,那就得改应用的逻辑,不利用存储,实时去数据库中查询,但是这个的SQL可就复杂了。我见过最长的 SQL 都可以快赶得上我大学毕业时候的毕业论文了。当然是有点夸张了。

用户评论