ClickHouse与esProc SPL性能对比

开源分析数据库 clickhouse 以快著称,真的如此吗?我们通过对比测试来验证一下。 clickhouse vs oracle
先用 clickhouse(简称 ch)、oracle 数据库(简称 ora)一起在相同的软硬件环境下做对比测试。测试基准使用国际广泛认可的 tpc-h,针对 8 张表,完成 22 条 sql 语句定义的计算需求(q1 到 q22)。测试采用单机 12 线程,数据总规模 100g。tpc-h 对应的 sql 都比较长,这里就不详细列出了。q1 是简单的单表遍历计算分组汇总,对比测试结果如下:ch 计算 q1 的表现要好于 ora,说明 ch 的列式存储做得不错,单表遍历速度很快。而 ora 主要吃亏在使用了行式存储,明显要慢得多了。但是,如果我们加大计算复杂度,ch 的表现怎么样呢?继续看 tpc-h 的 q2、q3、q7,测试结果如下:计算变得复杂之后,ch 性能出现了明显的下降。q2 涉及数据量较少,列存作用不大,ch 性能和 ora 几乎一样。q3 数据量较大,ch 占了列存的便宜后超过了 ora。q7 数据也较大,但是计算复杂,ch 性能还不如 ora。做复杂计算快不快,主要看性能优化引擎做的好不好。ch 的列存占据了巨大的存储优势,但竟然被 ora 用行式存储赶上,这说明 ch 的算法优化能力远不如 ora。tpc-h 的 q8 是更复杂一些的计算,子查询中有多表连接,ch 跑了 2000 多秒还没有出结果,应该是卡死了,ora 跑了 192 秒。q9 在 q8 的子查询中增加了 like,ch 直接报内存不足的错误了,ora 跑了 234 秒。其它还有些复杂运算是 ch 跑不出来的,就没法做个总体比较了。ch 和 ora 都基于 sql 语言,但是 ora 能优化出来的语句,ch 却跑不出来,更证明 ch 的优化引擎能力比较差。坊间传说,ch 只擅长做单表遍历运算,有关联运算时甚至跑不过 mysql,看来并非虚妄胡说。想用 ch 的同学要掂量一下了,这种场景到底能有多大的适应面? esproc spl 登场
开源 esproc spl 也是以高性能作为宣传点,那么我们再来比较一下。仍然是跑 tpc-h 来看 :q2、q3、q7 这些较复杂的运算,spl 比 ch 和 ora 跑的都快。ch 跑不出结果的 q8、q9,spl 分别跑了 37 秒和 68 秒,也比 ora 快。原因在于 spl 可以采用更优的算法,其计算复杂度低于被 ora 优化过的 sql,更远低于 ch 执行的 sql,再加上列存,最终是用 java 开发的 spl 跑赢了 c++ 实现的 ch 和 ora。大概可以得到结论,esproc spl 无论做简单计算,还是复杂计算性能都非常好。不过,q1 这种简单运算,ch 比 spl 还是略胜了一筹。似乎可以进一步证明前面的结论,即 ch 特别擅长简单遍历运算。且慢,spl 还有秘密武器。spl 的企业版中提供了列式游标机制,我们再来对比测试一下:在 8 亿条数据量下,做最简单的分组汇总计算,对比 spl(使用列式游标)和 ch 的性能。(采用的机器配置比前面做 tpc-h 测试时略低,因此测出的结果不同,不过这里主要看相对值。)简单分组汇总对应 ch 的 sql 语句是:sql1:         select mod(id, 100) as aid, max(amount) as amaxfrom test.tgroup by mod(id, 100) 这个测试的结果是下图这样:spl 使用列式游标机制之后,简单遍历分组计算的性能也和 ch 一样了。如果在 tpc-h 的 q1 测试中也使用列式游标,spl 也会达到和 ch 同样的性能。测试过程中发现,8 亿条数据存成文本格式占用磁盘 15g,在 ch 中占用 5.4g,spl 占用 8g。说明 ch 和 spl 都采用了压缩存储,ch 的压缩比更高些,也进一步证明 ch 的存储引擎做得确实不错。不过,spl 也可以达到和 ch 同样的性能,这说明 spl 存储引擎和算法优化做得都比较好,高性能计算能力更加均衡。当前版本的 spl 是用 java 写的,java 读数后生成用于计算的对象的速度很慢,而用 c++ 开发的 ch 则没有这个问题。对于复杂的运算,读数时间占比不高,java 生成对象慢造成的拖累还不明显;而对于简单的遍历运算,读数时间占比很高,所以前面测试中 spl 就会比 ch 更慢。列式游标优化了读数方案,不再生成一个个小对象,使对象生成次数大幅降低,这时候就能把差距拉回来了。单纯从存储本身看,spl 和 ch 相比并没有明显的优劣之分。接下来再看常规 topn 的对比测试,ch 的 sql 是:sql2:   select * from test.t order by amount desc limit 100 对比测试结果是这样的:单看 ch 的 sql2,常规 topn 的计算方法是全排序后取出前 n 条数据。数据量很大时,如果真地做全排序,性能会非常差。sql2 的测试结果说明,ch 应该和 spl 一样做了优化,没有全排序,所以两者性能都很快,spl 稍快一些。也就是说,无论简单运算还是复杂运算,esproc spl 都能更胜一筹。 进一步的差距
差距还不止于此。正如前面所说,ch 和 ora 使用 sql 语言,都是基于关系模型的,所以都面临 sql 优化的问题。tpc-h 测试证明,ora 能优化的一些场景 ch 却优化不了,甚至跑不出结果。那么,如果面对一些 ora 也不会优化的计算,ch 就更不会优化了。比如说我们将 sql1 的简单分组汇总,改为两种分组汇总结果再连接,ch 的 sql 写出来大致是这样:sql3:                         select *from ( select mod(id, 100) as aid, max(amount) as amax from test.t group by mod(id, 100) ) a   join (   select floor(id / 200000) as bid, min(amount) as bmin   from test.t   group by floor(id / 200000)  ) b   on a.aid = b.bid 这种情况下,对比测试的结果是 ch 的计算时间翻倍,spl 则不变:
这是因为 spl 不仅使用了列式游标,还使用了遍历复用机制,能在一次遍历过程中计算出多种分组结果,可以减少很多硬盘访问量。ch 使用的 sql 无法写出这样的运算,只能靠 ch 自身的优化能力了。而 ch 算法优化能力又很差,其优化引擎在这个测试中没有起作用,只能遍历两次,所以性能下降了一倍。spl 实现遍历复用的代码很简单,大致是这样:   a b
1 =file(topn.ctx).open().cursor@mv(id,amount)
2 cursor a1 =a2.groups(id%100:aid;max(amount):amax)
3 cursor =a3.groups(id200000:bid;min(amount):bmin)
4 =a2.join@i(aid,a3:bid,bid,bmin)
再将 sql2 常规 topn 计算,调整为分组后求组内 topn。对应 sql 是:
sql4:                             select gid, grouparray(100)(amount) as amountfrom(     select mod(id, 10) as gid, amount   from test.topn      order by gid asc, amount desc) as agroup by gid 这个分组 topn 测试的对比结果是下面这样的:
ch 做分组 topn 计算比常规 topn 慢了 42 倍,说明 ch 在这种情况下很可能做了排序动作。也就是说,情况复杂化之后,ch 的优化引擎又不起作用了。与 sql 不同,spl 把 topn 看成是一种聚合运算,和 sum、count 这类运算的计算逻辑是一样的,都只需要对原数据遍历一次。这样,分组求组内 topn 就和分组求和、计数一样了,可以避免排序计算。因此,spl 计算分组 topn 比 ch 快了 22 倍。而且,spl 计算分组 topn 的代码也不复杂:   a
1 =file(topn.ctx).open().cursor@mv(id,amount)
2 =a1.groups(id%10:gid;top(10;-amount)).news(#2;gid,~.amount)
不只是跑得快
再来看看电商系统中常见的漏斗运算。spl 的代码依然很简洁:   a b
1 =[etype1,etype2,etype3] =file(event.ctx).open()
2 =b1.cursor(id,etime,etype;etime>=date(2021-01-10) && etimet && etime= to_date('2021-01-10', 'yyyy-mm-dd') and etime= to_date('2021-01-10', 'yyyy-mm-dd') and e2.etime t1 and e2.etime = to_date('2021-01-10', 'yyyy-mm-dd') and e3.etime t2 and e3.etime < t1 + 7 and eventtype='eventtype3' and … group by 1)select sum(step1) as step1, sum(step2) as step2, sum(step3) as step3from e1 left join e2 on e1.gid = e2.gid left join e3 on e2.gid = e3.gid ora 的 sql 写出来要三十多行,理解起来有相当的难度。而且这段代码和漏斗的步骤数量相关,每增加一步数就要再增加一段子查询。相比之下,spl 就简单得多,处理任意步骤数都是这段代码。这种复杂的 sql,写出来都很费劲,性能优化更无从谈起。而 ch 的 sql 还远不如 ora,基本上写不出这么复杂的逻辑,只能在外部写 c++ 代码实现。也就是说,这种情况下只能利用 ch 的存储引擎。虽然用 c++ 在外部计算有可能获得很好的性能,但开发成本非常高。类似的例子还有很多,ch 都无法直接实现。 总结一下:ch 计算某些简单场景(比如单表遍历)确实很快,和 spl 的性能差不多。但是,高性能计算不能只看简单情况快不快,还要权衡各种场景。对于复杂运算而言,spl 不仅性能远超 ch,代码编写也简单很多。spl 能覆盖高性能数据计算的全场景,可以说是完胜 ch。

镀锌钢板对人体有害吗,测量镀锌板宽度仪器的推荐
骁龙845不及苹果A11,三星Galaxy S9和LG G7有幸搭载
2018年全球存储器产业的设备总投资额为440亿美元
说好的VR元年呢?国产VR市场乱象丛生
国惠投资与正威国际集团签署投资合作协议,将投资约150亿元重点布局半导体领域
ClickHouse与esProc SPL性能对比
超高精度可编程电压源如何采用ADI/LTC产品组合实现
微软开始测试 21H1 的功能体验包功能 无需大版本更新即可体验
两条告诉你为什么输配电成本有待进一步降低
华为放弃收购3Leaf,致美国政府公开信全文
利用8位单片机设计一款灵活的低成本血糖仪的教程分析
ESCRYPT安全解决方案遍布全球数百万辆汽车
游戏GPU短缺有望持续至2022年
管道流量计的测量原理
架构师为何要为嵌入式应用程序实施HMP系统
首届半导体产业峰会暨芯智库成立大会开幕
怎样用PVC管制作超酷高速跑车
FPC高速信号的应用实例解析
铅酸蓄电池达不到设计使用寿命的原因
我国明确TD-LTE频率规划 频谱是TD-SCDMA数倍