开源分析数据库ClickHouse是出了名的快,是真的吗?下面通过对比测试来验证一下。ClickHousevsOracle首先使用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语言,但是CH不能运行ORA可以优化的语句,这就证明CH的优化引擎比较差。民间传说,CH只擅长单表遍历操作,关联操作连MySQL都跑不起来。看来不是假的。想用CH的同学要权衡一下。这个场景能有多大的适应性?集算器SPL登场开源集算器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。大概可以得出这样的结论,集算器SPL在简单计算和复杂计算中的表现都非常好。不过对于Q1的简单操作,CH略胜于SPL。似乎进一步支持了之前的结论,即CH特别擅长简单的遍历操作。等一下,SPL有秘诀。SPL企业版提供了柱状游标机制。做个对比测试:8亿条数据,做最简单的分组汇总计算,比较SPL(使用柱状游标)和CH的性能。(使用的机器配置比之前的TPC-H测试略低,所以实测结果不同,这里主要看相对值。)CH对应的SQL语句进行简单分组汇总为:SQL1:SELECTmod(id,100)ASAid,max(amount)ASAmaxFROMtest.tGROUPBYmod(id,100)本次测试结果如下图所示:SPL使用柱状游标机制后,性能简单遍历组计算同CH。如果在TPC-H的Q1测试中也使用columnarcursor,SPL也会达到和CH一样的性能。测试时发现,8亿条文本格式的数据,占用磁盘15G,CH占5.4G,SPL占8G。说明CH和SPL都使用了压缩存储,而且CH的压缩率更高,进一步证明CH的存储引擎确实不错。不过SPL也能达到和CH一样的性能,说明SPL的存储引擎和算法优化更好,高性能计算能力更均衡。现在版本的SPL是用Java写的,读取后生成计算对象比较慢,而用C++开发的CH则没有这个问题。对于复杂操作,读取时间占比不高,Java对象生成慢带来的拖累不明显;对于简单的遍历操作,读取时间占比很高,所以SPL会比前面测试的CH慢。柱状游标优化了读取方案,不再一个一个生成小对象,使对象生成次数大大减少,此时可以拉回差距。从存储本身来看,SPL和CH并没有明显的区别。接下来看常规TopN的对比测试。CH的SQL为:SQL2:SELECT*FROMtest.tORDERBYamountDESCLIMIT100对比测试结果如下:只看CH的SQL2,常规TopN的计算方式是全排序然后取出前N条数据。当数据量很大的时候,如果真的做全排序,性能会很差。SQL2的测试结果表明CH应该和SPL一样优化,没有全排序,所以两者的性能都很快,SPL稍微快一些。也就是说,集算器SPL可以优于简单和复杂的计算。进一步的差距还不止于此。前面提到CH和ORA使用的都是SQL语言,都是基于关系模型的,所以都面临着SQL优化的问题。TPC-H测试证明了一些ORA可以优化的场景CH无法优化,甚至跑出结果。那么,如果面对一些ORA不会优化的计算,CH也不会优化。比如我们把SQL1的简单分组汇总改成两种分组汇总,然后连接起来,CH的SQL可以这样写:SQL3:SELECT*FROM(SELECTmod(id,100)ASAid,max(金额)ASAmaxFROMtest.tGROUPBYmod(id,100))AJOIN(SELECTfloor(id/200000)ASBid,min(金额)ASBminFROMtest.tGROUPBYfloor(id/200000))BONA.在Aid=B.Bid的情况下,对比测试的结果是CH的计算时间增加了一倍,而SPL的计算时间不变:这是因为SPL不仅使用了柱状游标,还使用了一种遍历复用机制,可以一次遍历。过程中会计算出多种分组结果,可以减少大量的硬盘访问。CH使用的SQL写不出这样的操作,只能靠CH自身的优化能力。但是,CH算法的优化能力很差。它的优化引擎在本次测试中不起作用,只能遍历两次,因此性能翻倍。SPL实现遍历复用的代码很简单,大致是这样的:AB1=file("topn.ctx").open().cursor@mv(id,amount)2cursorA1=A2.groups(id%100:Aid;max(amount):Amax)3cursor=A3.groups(id\200000:Bid;min(amount):Bmin)4=A2.join@i(Aid,A3:Bid,Bid,Bmin)然后SQL2常规TopNcalculation,调整为分组后找到组内的TopN。对应的SQL为:SQL4:SELECTgid,groupArray(100)(amount)ASamountFROM(SELECTmod(id,10)ASgid,amountFROMtest.topnORDERBYgidASC,amountDESC)ASaGROUPBYgid本组TopNtest对比结果如下:CH的groupTopN计算比常规TopN慢了42倍,说明CH很可能在这种情况下进行了排序动作。也就是说,情况复杂之后,CH的优化引擎就不会再起作用了。与SQL不同的是,SPL将TopN视为一种聚合操作,与sum、count等操作具有相同的计算逻辑,只需要遍历一次原始数据即可。这样,通过分组计算组内的TopN与通过分组求和计数是一样的,可以避免排序计算。因此,SPL计算组TopN的速度比CH快22倍。而且SPL计算组TopN的代码并不复杂:A1=file("topn.ctx").open().cursor@mv(id,amount)2=A1.groups(id%10:gid;top(10;-amount)).news(#2;gid,~.amount)不只是跑得快,我们来看看电商系统中常见的漏斗计算。SPL的代码还是很简单的:AB1=["etype1","etype2","etype3"]=file("event.ctx").open()2=B1.cursor(id,etime,etype;etime>=date("2021-01-10")&&etime
