电子说
ClickHouse vs Oracle
先用 ClickHouse(简称 CH)、Oracle 数据库(简称 ORA)一起在相同的软硬件环境下做对比测试。测试基准使用国际广泛认可的 TPC-H,针对 8 张表,完成 22 条 SQL 语句定义的计算需求(Q1 到 Q22)。测试采用单机 12 线程,数据总规模 100G。TPC-H 对应的 SQL 都比较长,这里就不详细列出了。Q1 是简单的单表遍历计算分组汇总,对比测试结果如下:esProc SPL 登场
开源 esProc SPL 也是以高性能作为宣传点,那么我们再来比较一下。仍然是跑 TPC-H 来看 :这个测试的结果是下图这样:SELECT mod(id, 100) AS Aid, max(amount) AS Amax
FROM test.t
GROUP BY mod(id, 100)
SELECT * FROM test.t ORDER BY amount DESC LIMIT 100
对比测试结果是这样的:进一步的差距
差距还不止于此。正如前面所说,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 则不变:
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 amount
FROM
(
SELECT
mod(id, 10) AS gid,
amount
FROM test.topn
ORDER BY
gid ASC,
amount DESC
) AS a
GROUP BY gid
这个分组 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") && etime |
|
3 | =A2.group(id).(~.sort(etime)) | =A3.new(~.select@1(etype==A1(1)):first,~:all).select(first) |
4 |
=B3.(A1.(t=if(#==1,t1=first.etime,if(t,all.select@1(etype==A1.~ && etime>t && etime |
|
5 | =A4.groups(;count(~(1)):STEP1,count(~(2)):STEP2,count(~(3)):STEP3) |
CH 的 SQL 无法实现这样的计算,我们以 ORA 为例看看三步漏斗的 SQL 写法:
ORA 的 SQL 写出来要三十多行,理解起来有相当的难度。而且这段代码和漏斗的步骤数量相关,每增加一步数就要再增加一段子查询。相比之下,SPL 就简单得多,处理任意步骤数都是这段代码。这种复杂的 SQL,写出来都很费劲,性能优化更无从谈起。而 CH 的 SQL 还远不如 ORA,基本上写不出这么复杂的逻辑,只能在外部写 C++ 代码实现。也就是说,这种情况下只能利用 CH 的存储引擎。虽然用 C++ 在外部计算有可能获得很好的性能,但开发成本非常高。类似的例子还有很多,CH 都无法直接实现。with e1 as (
select gid,1 as step1,min(etime) as t1
from T
where etime>= to_date('2021-01-10', 'yyyy-MM-dd') and etime<to_date('2021-01-25', 'yyyy-MM-dd')
and eventtype='eventtype1' and …
group by 1
),
with e2 as (
select gid,1 as step2,min(e1.t1) as t1,min(e2.etime) as t2
from T as e2
inner join e1 on e2.gid = e1.gid
where e2.etime>= to_date('2021-01-10', 'yyyy-MM-dd') and e2.etime<to_date('2021-01-25', 'yyyy-MM-dd')
and e2.etime > t1
and e2.etime < t1 + 7
and eventtype='eventtype2' and …
group by 1
),
with e3 as (
select gid,1 as step3,min(e2.t1) as t1,min(e3.etime) as t3
from T as e3
inner join e2 on e3.gid = e2.gid
where e3.etime>= to_date('2021-01-10', 'yyyy-MM-dd') and e3.etime<to_date('2021-01-25', '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 step3
from
e1
left join e2 on e1.gid = e2.gid
left join e3 on e2.gid = e3.gid
总结一下:CH 计算某些简单场景(比如单表遍历)确实很快,和 SPL 的性能差不多。但是,高性能计算不能只看简单情况快不快,还要权衡各种场景。对于复杂运算而言,SPL 不仅性能远超 CH,代码编写也简单很多。SPL 能覆盖高性能数据计算的全场景,可以说是完胜 CH。
全部0条评论
快来发表一下你的评论吧 !