Comparación de rendimiento de la base de datos de análisis de código abierto ClickHouse y esProc SPL de código abierto

Estoy participando en el "Programa de Vela · Nuggets"

ClickHouse frente a Oracle

La base de datos de análisis de código abierto ClickHouse es conocida por ser rápida, ¿es eso cierto? Vamos a verificarlo mediante una prueba de comparación.

Primero use ClickHouse (denominado CH) y la base de datos de Oracle (denominada ORA) para realizar una prueba comparativa en el mismo entorno de software y hardware. El punto de referencia de prueba utiliza el TPC-H reconocido internacionalmente para completar los requisitos de cálculo (Q1 a Q22) definidos por 22 declaraciones SQL para 8 tablas. La prueba utiliza una sola máquina con 12 subprocesos y el tamaño total de los datos es de 100G. El SQL correspondiente a TPC-H es relativamente largo, por lo que no se enumerará en detalle aquí.

Q1 es un resumen simple del grupo de cálculo transversal de una sola tabla, los resultados de la prueba de comparación son los siguientes:

..

El rendimiento de CH para calcular Q1 es mejor que el de ORA, lo que indica que el almacenamiento en columnas de CH funciona bien y que el recorrido de una sola tabla es rápido. La principal desventaja de ORA es el uso del almacenamiento de filas, que obviamente es mucho más lento.

Pero, ¿cómo funciona CH si aumentamos la complejidad computacional? Continúe mirando Q2, Q3 y Q7 de TPC-H. Los resultados de la prueba son los siguientes:

..

Después de que el cálculo se volvió más complicado, el rendimiento de CH se redujo significativamente. Q2 implica una pequeña cantidad de datos, el almacenamiento en columnas tiene poco efecto y el rendimiento de CH es casi el mismo que el de ORA. La cantidad de datos en el tercer trimestre es grande y CH ha superado a ORA después de aprovechar el almacenamiento en columnas. Los datos de Q7 también son más grandes, pero el cálculo es complejo y el rendimiento de CH no es tan bueno como el de ORA.

Si es rápido hacer cálculos complejos depende principalmente de si el motor de optimización del rendimiento está funcionando bien. El almacenamiento en columnas de CH ocupa una gran ventaja de almacenamiento, pero ha sido superado por el almacenamiento en filas de ORA, lo que muestra que la capacidad de optimización de algoritmos de CH es mucho menor que la de ORA.

Q8 de TPC-H es un cálculo más complicado. Hay varias combinaciones de tablas en la subconsulta. CH se ejecutó durante más de 2000 segundos y aún no obtuvo el resultado. Debería estar atascado y ORA se ejecutó durante 192 segundos. Q9 agregó me ​​gusta a la subconsulta de Q8, CH informó directamente un error de falta de memoria y ORA se ejecutó durante 234 segundos. Hay algunas otras operaciones complejas que CH no puede ejecutar, por lo que no hay forma de hacer una comparación general.

Tanto CH como ORA se basan en el lenguaje SQL, pero CH no puede ejecutar las declaraciones que ORA puede optimizar, lo que demuestra aún más que el motor de optimización de CH es relativamente pobre.

Se rumorea que CH solo es bueno para realizar operaciones transversales de una sola tabla, e incluso no puede ejecutar MySQL cuando hay operaciones asociadas.No parece ser falso. Los estudiantes que quieran usar CH necesitan sopesarlo ¿Cuán adaptable puede ser este escenario?

esProc SPL debuta

开源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 Amax
FROM test.t
GROUP 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(id\200000: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测试的对比结果是下面这样的:

..

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") && etime<date("2021-01-25") && A1.contain(etype) && …)
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<t1+7).etime, null))))
5 =A4.groups(;count(~(1)):STEP1,count(~(2)):STEP2,count(~(3)):STEP3)

CH的SQL无法实现这样的计算,我们以ORA为例看看三步漏斗的SQL写法:

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-10', '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 t2
       and e3.etime < t1 + 7
       and eventtype='eventtype3' and …
    group by 1
)
select
    sum(step1) as step1,
    suma (paso 2) como paso 2,
    suma (paso 3) como paso 3 
de 
    e1 a 
    la izquierda se une a e2 en e1.gid = e2.gid 
    a la izquierda se une a e3 en e2.gid = e3.gid

El SQL de ORA requiere más de 30 líneas para escribirse, lo cual es bastante difícil de entender. Y este código está relacionado con la cantidad de pasos en el embudo, y cada paso adicional requiere una subconsulta adicional. Por el contrario, SPL es mucho más simple y es este código el que maneja cualquier número de pasos.

Este tipo de SQL complejo es muy laborioso de escribir, y es imposible hablar de optimización del rendimiento.

Y el SQL de CH es muy inferior a ORA, básicamente no puede escribir una lógica tan compleja y solo puede escribir código C ++ externamente. Es decir, en este caso solo se puede utilizar el motor de almacenamiento de CH. Si bien es posible obtener un buen rendimiento con computación externa en C++, el costo de desarrollo es muy alto. Hay muchos ejemplos similares y CH no puede implementarlos directamente.

Para resumir: CH calcula algunos escenarios simples (como el recorrido de una sola tabla) muy rápido, aproximadamente con el mismo rendimiento que SPL. Sin embargo, la computación de alto rendimiento no solo puede mirar la velocidad de situaciones simples, sino que también pesa varios escenarios. Para operaciones complejas, SPL no solo funciona mucho mejor que CH, sino que también simplifica mucho la escritura de código. SPL puede cubrir toda la escena de la computación de datos de alto rendimiento, lo que puede decirse que es una victoria completa sobre CH.

Referirse a

Supongo que te gusta

Origin juejin.im/post/7145741592031133732
Recomendado
Clasificación