mysql分表聚合查询_数据库中间件技术之~分库分表中的聚合

简介

这篇文章可能有点枯燥,主要涉及的从SQL的原理设计分库分表操作的要点。耐心看完,一定会有收获。

但是在做数据库中间件的研发的时候不得不考虑这些问题,这个也是我司在数据库中间件开发过程中踩的坑之一,我尽可能用简洁易懂的语言说明踩坑的原理和解决方案,以后有机会会慢慢多写一点。

单表数据过大的时候,往往需要分表,有几种分表方式,例如针对用户数据可以按照用户ID的Hash进行分表,对于时间序列的流水账(比如IoT,我司是车联网,就是按天分表)采用按小时,按天,按月等分表方式。

这里说一下多表查询中的聚合逻辑,在这些聚合逻辑的说明中,我们都以ANSI 92 SQL为标准。

一般聚合逻辑

SUM/COUNT/MIN/MAX/AVG/……

除了AVG计算的情形比较特殊,需要拆分为SUM和COUNT单独计算:

select avg(x) as ax from t_xxx where y=1;

拆分为:

select sum(x) as ax_num, count(x) as ax_den from t_xxx_{SUB-TABLE-ID} where y=1;

最后使用ax_num/ax_den计算得到结果。

其余的基本上就是在各个分表做操作以后再次聚合即可(即求最大值的最大值,求和的和……),这个没什么可说的。

下面我们只针对SUM、MIN,MAX,COUNT作讨论。

带有其他坑爹约束时候的聚合函数详解

如果一个语句带有Group By、Order By,Limit的时候事情就不是那么简单了。(TOP我们可以解析为这三个操作的组合上,暂不考虑)

正常来说,我们应该把所有的子句在各个分表上都执行一遍然后再聚合,但是ANSI SQL眉头一皱,发现事情没有那么简单:

正常聚合即可的操作组合

group by a

group by a order by b

group by a limit x, y

limit x, y

需要改变SQL语句的坑爹操作

1、order by b limit x, y

这个时候需要将在子库上运行的语句变为order by b limit 0, y。

原理很简单,举个小栗子就可以说明:如果要求全年级考试成绩的5~10名,那么应该是拿出每个班的1~10名进行比较而不是拿出每个班的5~10名进行比较。

2、group by a order by b limit x, y

这个时候需要去掉limit条件,变为group by a order by b,这个原理也不复杂,也是一个小栗子就可以说明:

如果要求考试总成绩的5~10名,那么应该将所有学生的成绩都算出来再求,而不是求每个考试科目的前十名,这样有可能会漏掉一些学生得到成绩。

注意点

两个需要改变limit条件的语句要慎用,否则可能会造成一些性能问题。

总结

分库分表是个好东西,但是不要滥用,单个MySQL的表撑个几百万到千万的数据是轻轻松松的,如果使用MongoDB到亿级别都是OK的,没有迫切的性能需求不要乱分表,否则考虑的事情就多了……

你可能感兴趣的:(mysql分表聚合查询)