有16个聚合方法,有几个方法有不同别名: COUNT COUNT_ALL(count(*)) 和 COUNT(字段),COUNT_ALL和COUNT合并,不存在COUNT_ALL这样的名字,都用COUNT SUM MIN MAX AVG GROUP_CONCAT STDDEV_SAMP 也叫: STDDEV STDDEV_POP 也叫: STDDEVP VAR_SAMP 也叫: VAR、VARIANCE VAR_POP 也叫: VARP BOOL_OR 也叫: SOME BOOL_AND 也叫: EVERY BIT_OR BIT_AND SELECTIVITY HISTOGRAM 这个聚合函数在H2的文档中没有介绍 聚合函数只能出现在select语句的"select (1)... from (2) ...."中的(1) static { addAggregate("COUNT", COUNT); addAggregate("SUM", SUM); addAggregate("MIN", MIN); addAggregate("MAX", MAX); addAggregate("AVG", AVG); addAggregate("GROUP_CONCAT", GROUP_CONCAT); addAggregate("STDDEV_SAMP", STDDEV_SAMP); addAggregate("STDDEV", STDDEV_SAMP); addAggregate("STDDEV_POP", STDDEV_POP); addAggregate("STDDEVP", STDDEV_POP); addAggregate("VAR_POP", VAR_POP); addAggregate("VARP", VAR_POP); addAggregate("VAR_SAMP", VAR_SAMP); addAggregate("VAR", VAR_SAMP); addAggregate("VARIANCE", VAR_SAMP); addAggregate("BOOL_OR", BOOL_OR); // HSQLDB compatibility, but conflicts with x > EVERY(...) addAggregate("SOME", BOOL_OR); addAggregate("BOOL_AND", BOOL_AND); // HSQLDB compatibility, but conflicts with x > SOME(...) addAggregate("EVERY", BOOL_AND); addAggregate("SELECTIVITY", SELECTIVITY); addAggregate("HISTOGRAM", HISTOGRAM); } 方法调用顺序: org.h2.expression.Aggregate.mapColumns(ColumnResolver, int) org.h2.expression.Aggregate.optimize(Session) org.h2.expression.Aggregate.updateAggregate(Session) //针对每行调用聚合方法 =>org.h2.expression.AggregateData.add(Database, boolean, Value) org.h2.expression.Aggregate.getValue(Session) //获得总结果 =>org.h2.expression.AggregateData.getValue(Database, boolean) 特殊聚合函数说明: 1. SELECTIVITY 是基于某个表达式(多数是单个字段)算不重复的记录数所占总记录数的百分比 org.h2.engine.Constants.SELECTIVITY_DISTINCT_COUNT默认是1万,这个值不能改, 对统计值影响很大。通常这个值越大,统计越精确,但是会使用更多内存。 SELECTIVITY越大,说明重复的记录越少,在选择索引时更有利。 并行算法实现: 将select SELECTIVITY(字段) 改成select count(字段), count(DISTINCT 字段) 然后再算: {总count(字段)/总count(DISTINCT 字段)} * 100 标准差在多节点上的并行算法是: 在每节点上先算: 记录数、字段和、字段平方和,然后归并所有节点上返回的这三个参数,最后标准差 = {字段平方总和/总记录数- (字段总和/总记录数)的平方} 的平方根。HBase也是这么做的。 所以结论是: 对于标准差的分布式并行计算算法的优化是将"select std(字段)"先改写成"select count(字段),sum(字段),sum(字段*字段)",归并后按此公式算: 标准差 = {字段平方总和/总记录数- (字段总和/总记录数)的平方} 的平方根 聚合函数从单结点扩展到多结点后复杂性增加了好多,就拿求平均数来说,当client接收到"select avg(字段) from 表"这样的sql后,需要改写sql,把avg换成count和sum,再加上有统计区间的where条件,变成"select count(字段), sum(字段) from 表 where 字段 between x and y",直接每个结点求avg是不对的 1 2 3 4 5 平均值: 3 (1-3)的平方 + (2-3)的平方 + (3-3)的平方 + (4-3)的平方 + (5-3)的平方 = 4 + 1 + 0 + 1 + 4 =10 标准差 = (10/5)的平方跟 =1.4 ================================ 1 2 3 平均值: 2 (1-2)的平方 + (2-2)的平方 + (3-2)的平方 = 1 + 0 + 1 = 2 标准差 = (2/3)的平方跟 = 0.8 ================================ 4 5 平均值: 4.5 (4-4.5)的平方 + (5-4.5)的平方 = 0.25 + 0.25 = 0.5 标准差 = (0.5/2)的平方跟 = 0.5 1 mean = 1; m2 = 0; 2 mean = 1.5; m2 = 0; 1 3 5 总和 1 + 3 + 5 平方和 1*1 + 3*3 + 5*5 行数 3 7 9 11 总和 7 + 9 + 11 平方和 7*7 + 9*9 + 11*11 行数 3 ============================ 两者汇总: 总和 (1 + 3 + 5) + (7 + 9 + 11) 平方和 (1*1 + 3*3 + 5*5) + (7*7 + 9*9 + 11*11) 行数 3 + 3 = 6 {(1 + 3 + 5) + (7 + 9 + 11)} / 6 {(1*1 + 3*3 + 5*5) + (7*7 + 9*9 + 11*11)} / 6 标准差: { {(1*1 + 3*3 + 5*5) + (7*7 + 9*9 + 11*11)} / 6 } - {{(1 + 3 + 5) + (7 + 9 + 11)} / 6} * {{(1 + 3 + 5) + (7 + 9 + 11)} / 6} = (1+9+25+49+81+121)/6 - (36/6) * (36/6) = 286/6 - (36/6) * (36/6) = 11.666666666666666666666666666667 = 3.4156502553198661277403462268404 (1-6) (3-6) (5-6) (7-6) (9-6) (11-6) 25 + 9 + 1 + 1 + 9 + 25 = 70 = 3.4156502553198661277403462268404 (x-2)*(x-2) = x*x-2x-2x+4 (x- {{(1 + 3 + 5) + (7 + 9 + 11)} / 6}) x1 * x1 - 2x * {{(1 + 3 + 5) + (7 + 9 + 11)} / 6} + {{(1 + 3 + 5) + (7 + 9 + 11)} / 6} (1 - (1 + 3 + 5)/3)的平方 + (3 - (1 + 3 + 5)/3)的平方 + (5 - (1 + 3 + 5)/3)的平方 1*1 - 2*1*(1 + 3 + 5)/3 + (1 + 3 + 5)/3*(1 + 3 + 5)/3 + 3*3 - 2*3*(1 + 3 + 5)/3 + (1 + 3 + 5)/3*(1 + 3 + 5)/3 + 5*5 - 2*5*(1 + 3 + 5)/3 + (1 + 3 + 5)/3*(1 + 3 + 5)/3 1*1 - (2*1*(1 + 3 + 5)/3 - (1 + 3 + 5)/3*(1 + 3 + 5)/3) + 3*3 - (2*3*(1 + 3 + 5)/3 - (1 + 3 + 5)/3*(1 + 3 + 5)/3) + 5*5 - (2*5*(1 + 3 + 5)/3 - (1 + 3 + 5)/3*(1 + 3 + 5)/3)