Java猿社区—ShardingSphere之分组groupby过多消耗内存的问题
Java猿社区—ShardingSphere之分组group by过多消耗内存的问题
ss的归并引擎包括分组归并,分组归并的情况最为复杂,它分为流式分组归并和内存分组归并。 流式分组归并要求SQL的排序项与分组项的字段以及排序类型(ASC或DESC)必须保持⼀致,否则只能通过内存归并才能保证其数据的正确性。
举例说明,假设根据科⽬分⽚,表结构中包含考⽣的姓名(为了简单起见,不考虑重名的情况)和分数。通过SQL获取每位考⽣的总分,可通过如下SQL:
groupby分组SELECT name,SUM(score)FROM t_score GROUP BY name ORDER BY name;
在分组项与排序项完全⼀致的情况下,取得的数据是连续的,分组所需的数据全数存在于各个数据结果集的当前游标所指向的数据值,因此可以采⽤流式归并。如下图所⽰。
进⾏归并时,逻辑与排序归并类似。 下图展现了进⾏next调⽤的时候,流式分组归并是如何进⾏的。
通过图中我们可以看到,当进⾏第⼀次next调⽤时,排在队列⾸位的t_score_java将会被弹出队列,并且将分组值同为“Jetty”的其他结果集中的数据⼀同弹出队列。 在获取了所有的姓名为“Jetty”的同学的分数之后,进⾏累加操作,那么,在第⼀次next调⽤结束后,取出的结果集是“Jetty”的分数总和。 与
此同时,所有的数据结果集中的游标都将下移⾄数据值“Jetty”的下⼀个不同的数据值,并且根据数据结果集当前游标指向的值进⾏重排序。 因此,包含名字顺着第⼆位的“John”的相关数据结果集则排在的队列的前列。
流式分组归并与排序归并的区别仅仅在于两点:
它会⼀次性的将多个数据结果集中的分组项相同的数据全数取出。
它需要根据聚合函数的类型进⾏聚合计算。
对于分组项与排序项不⼀致的情况,由于需要获取分组的相关的数据值并⾮连续的,因此⽆法使⽤流式归并,需要将所有的结果集数据加载⾄内存中进⾏分组和聚合。 例如,若通过以下SQL获取每位考⽣的总分并按照分数从⾼⾄低排序:
SELECT name,SUM(score)FROM t_score GROUP BY name ORDER BY score DESC;
那么各个数据结果集中取出的数据与排序归并那张图的上半部分的表结构的原始数据⼀致,是⽆法进⾏流式归并的。
当SQL中只包含分组语句时,根据不同数据库的实现,其排序的顺序不⼀定与分组顺序⼀致。 但由于
排序语句的缺失,则表⽰此SQL并不在意排序顺序。 因此,ShardingSphere通过SQL优化的改写,⾃动增加与分组项⼀致的排序项,使其能够从消耗内存的内存分组归并⽅式转化为流式分组归并⽅案。
建议在开发时,使⽤group by语句时候,尽量排序项与分组项的字段以及排序类型保持⼀致。如果没办法保持,先预估下查询的数据量可能占⽤的内存⼤⼩和产品做好业务折衷,

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。