【数据蒋堂】第 45 期:怎样看待大数据计算语法向 SQL 回归

虽然我们说了不少 SQL 在性能上的不足,但是,回归 SQL 却是当前大数据计算语法的一个发展倾向。在 Hadoop 体系中,早期的 PIG Latin 已经被淘汰,而 Hive 却一直坚挺;Spark 上也在更多地使用 Spark SQL,而 Scala 反而少很多。其它一些新的大数据计算体系一般也将 SQL 作为首选的计算语法,经过几年时间的混战,现在 SQL 又逐步拿回了主动权。

这个现象,大概有这么两个原因:

1. 实在没什么别的好用

关系数据库过于普及,程序员对 SQL 相当熟悉,甚至思维习惯都是 SQL 式的。SQL 用来做一些常规查询也比较简单,虽然用于处理复杂的过程计算或有序运算并不方便,但其它那些替代技术也好不到哪里去,碰到 SQL 难写的运算一样要写和 UDF 相当的复杂代码,反正都是麻烦,还不如继续用 SQL。

2. 大数据厂商的鼎力支持

大数据的技术本质是高性能,而 SQL 是性能比拼的关键阵地。比性能要面对同样的运算才有意义,过于专门和复杂的运算涉及的影响因素太多,不容易评估出大数据平台本身的能力。而 SQL 有国际标准的 TPC 系列,所有用户都看得懂,这样就有明确的可比性,厂商也会把性能优化的重点放在 SQL 上。

但是,无论厂商怎样努力优化 SQL 的性能,仍然在许多场景无法提高计算性能。

对于比较简单的查询,特别是多维分析式的查询,基本上都能用 SQL 方便地描述。而且这种运算被传统数据库厂商研究了几十年,实践出很多行之有效的优化手段。而 Hadoop 这种新型大数据平台,正好可以实习和实施这些经验,就可能获得较好的性能体验。

对于更常见的过程性计算,SQL 就不太好用了,开发困难,代码要写很长,这时候优化 SQL 对于提高性能也很难有什么帮助。

什么是过程性计算呢?就是一步写不出来,需要多次分步运算,特别是与数据次序相关的运算。

我们举几个例子来看:

一周内累计登录时长超过一小时的用户占比,但要除去登录时长小于 10 秒的误操作情况

信用卡在最近三个月内最长连续消费的天数分布情况,考虑实施连续消费 10 天后积分三倍的促销活动

一个月中有多少用户在 24 小时连续操作了查看商品后加入购物车并购买的的动作,有多少用户在中间步骤中放弃?

……

(为了便于理解,这些例子已经做了简化,实际情况的运算还要复杂很多)

这类过程性运算,用 SQL 写出来的难度就很大,经常还要写 UDF 才能完成。如果 SQL 写都写不出来,那么指望优化 SQL 来提高性能也就无从谈起了。有时候能用 SQL 勉强写出来,代码也会相当复杂,而复杂 SQL 的优化效果是很差的,在嵌套几层之后,数据库引擎也会晕掉,不知道如何优化。

提高这类复杂运算的性能,指望计算平台的自动优化就靠不住了,根本手段还要靠写出高性能的算法。象过程式运算中还常常需要保存中间结果以复用,SQL 需要用临时表,多了 IO 操作就会影响性能,这都不是引擎优化能解决的事情,必须要去改写计算过程。

本质上,提高性能还是降低开发难度。软件无法提高硬件的性能,只能想办法设计复杂度更低的算法,而如果能够快速低成本地实现这些算法,那就可以达到提高性能的目标。如果语法体系难以甚至没办法描述高性能算法,必须迫使程序员采用复杂度较高的算法,那也就很难再提高性能了。优化 SQL 运算无助于降低它的开发难度,SQL 语法体系就是那样,无论怎样优化它的性能,开发难度并不会改变,很多高性能算法仍然实现不了,也就难以实质性地提高运算性能。

编写 UDF 在许多场景时确实能提高性能,但一方面开发难度很大,另一方面这是程序员硬写的,也不能利用到 SQL 引擎的优化能力。而且经常并不能将完整运算都写成 UDF,只能使用计算平台提供的接口,仍然要在 SQL 框架使用它的数据类型,这样还是会限制高性能算法的实现。

根本的解决方法,还是要让大数据平台真地有一些更好用的语法。