SPL 云数据仓库

市场上绝大多数(甚至可以说是全部)云数据仓库都是基于 SQL 的,毕竟数据仓库的主要功能是分析计算,其它 NoSQL 技术的优势主要在 TP,在 AP 方面远远不敌 SQL。参与竞争的云服务商也是这么想的,认为只要提供了 SQL,功能层面的事就算 OK 了,其它要比拼的就是性能、运维以及价钱等等了。

这当然是可行的解决方案,而且已经有了不少成功的服务商。

但是,50 年前发明的 SQL,真地那么适合用来实现近年才时髦的云上数据分析吗?

SPL 作为新的数据计算技术,是不是更合适呢?

云的基本特征实现

我们先来比较云服务的几个特征在 SQL 和 SPL 下实现的情况。

1. 弹性计算

云服务要求弹性计算,弹性计算通常要求存算分离(这里的道理就不赘述了)。但 SQL(也就是 RDB)在历史上是没考虑过存算分离的,经常是打穿文件系统直接访问硬盘的。要改造成存算分离的机制,使用网络文件系统以及云上的对象存储时,就要从底层重构,这是个复杂的任务,也就会带来不少实施风险。所以,存算分离是近年来 SQL 数据库的一个技术热点。

SPL 的存储建立在文件系统上,天然就支持网络文件系统,技术上没什么要研究的。使用云上的对象存储也也很容易,只要简单做个有缓存的文件对象就行了(业界也有不少这方面的成熟开源技术),实现存算分离非常简单。

弹性计算还要求能迅速启动新的计算节点,但执行 SQL 需要事先加载元数据,数据结构较复杂时一次性全加载需要耗费不少时间从而影响计算节点的迅速启动。要避免加载元数据的时间,可以有个中心管理着所有用户的元数据,相当已经加载过了,但这会导致运维复杂化并且中心负担沉重(云上用户数通常非常多);把元数据拆散后再临时加载(用到哪些加载哪些)也会导致管理复杂化并且总加载时间会更长了。总之没有什么都好的办法。

SPL 没有元数据,直接执行脚本就行了。

2. 多租户

多租户是云服务商的追求,云本来就要占这种便宜来提高硬件利用率。

还是因为有元数据,执行 SQL 的 VM 在不同用户之间不能混用,需要隔离好。某个 VM 用来执行另一个任务时需要更换元数据,运维也复杂化了。

SPL 没有元数据,用户之间甚至不需要隔离,不同任务可以混用同一个 JVM 工作,只需要处理负载均衡(SQL 也要处理)就行了,运维非常简单。

3.Serverless

Serverless 也是近期较热的概念。

又是因为有元数据,相当于 SQL 执行时后台要有个和前端用户有关的状态环境,这和 serverless 理念相悖。当然也可以透明地模拟出 serverless 的效果,但仍然面对前述的元数据加载及其导致的运维复制化问题。

SPL 没有元数据,直接运行服务脚本就行了。

关键差异:数据组织

从上面的讨论看,有没有元数据是 SQL 和 SPL 在云架构上的一个重要差别,没有元数据的 SPL 云要比 SQL 云更轻。

这里的根本差异在于 SQL 和 SPL 的数据组织不同。

SQL 的数据组织在逻辑上是整体化的,某个主题下的数据形成一个数据库,有一套元数据来描述库内数据的结构及关系。一个数据库在逻辑上是一个整体,有着明确的库内和库外的差别,不同数据库之间的数据不能随意组合和运算,这也就是我们常说的封闭性。早期数据库设计成这样,主要原因是为了保证数据的一致性,这对于 TP 业务是非常重要的。但是,对于以分析计算为主的 AP 业务,这个封闭性并没有多大意义,但关系数据库一直这么设计,这个架构也被继承下来了,上了云也依然是这个样子。

有元数据时,就如上面所说,会加大弹性计算、多租户和 serverless 的实现复杂度,不是说做不了,但会推高运维成本。

封闭性的伤害还不止于此。

现代数据应用的数据源更为广泛,经常会面对五花八门的数据来源和类型。封闭的 SQL 数据库不能针对库外的数据开放其计算能力,就只能把外部数据先导入才能计算。这会增加一步 ETL 动作,增大工作量并加大数据库负担的同时,还丧失了数据的实时性。这些外部数据的格式常常不规范,导入进有强约束的数据库并不是一件很容易的事。而且,即使做 ETL 也要先把未整理的数据先入库才能利用数据库的计算能力,结果把 ETL 做成 ELT,加大数据库负担。所有这些都可以做到,但无疑都会推高运维成本。

这种机制还不方便用户自由实施空间换时间。我们知道,存储资源相对于计算资源要便宜得多,如果我们针对不同计算目标把数据以多种方式冗余存储,就可能获得更好的查询体验。但是,SQL 要用表来存储数据,自建表太多又会导致元数据变大,而且严重增加运维成本(很多大型机构的中央数据仓库中会有成千上万的中间表,积累多年而不敢删除,元数据极为庞大。发明关系数据库的时候应该不会想到数据表数量会多到万这个量级)。

SQL 这种沉重封闭的整体化数据组织已深入到方方面面,要彻底改革也不是件容易的事。

SPL 的数据组织在逻辑上是碎片化的,没有主题的概念,也就没有元数据,当然更没有库内库外之分。随便什么数据,只要能访问到就能一起参与运算,无非只是不同数据源的访问性能不同。SPL 为了高性能设计了一些特殊的数据存储格式(列存、压缩等),但其逻辑地位和某个文本文件或者 Restful 上取出来的数据并没有区别,来自 SQL 数据库的数据也一样可以处理。这就是所谓计算能力的开放性。

物理存储使用文件系统,可以天然支持存算分离。没有元数据,就容易实现轻量级的弹性计算、多租户和 serverless。

开放的计算能力,做数据整理时没有入库的动作,直接针对数据计算就行了。需要其它数据源的混合运算时也直接做,不仅更轻量还能更实时。

用户可以随意设计空间换时间的方案,无非就是多存几个文件,即使冗余数据文件多到上万(现代文件系统处理这个规模的文件数据很轻松)也完全不会发生元数据庞大(根本就没有)的负担。使用文件系统的树状结构很容易分门别类管理这些数据文件,运维成本也不高。

SPL 的数据组织方式天然轻量开放,很适合移到云上。

关键差异:语言能力

SPL 和 SQL 还有一个重要差异在于我们常说的语言能力及其导致的算法实现能力,这对于云的应用成本也会巨大的影响。

其实,我们都知道,SQL 的语言能力并不完善,即使只是数据任务也常常难以独立完成。比如我们经常用举例子的股票连涨问题以及更复杂一些的电商漏斗运算(这些并不是多奇怪的需求,业务中经常会碰到),很多程序员看到这种问题会条件反射般地立即说这事不适合用 SQL 做,应该读出来用 Python 或 Java 来写。

这个条件反射没有错,SQL 写这种运算确实很烦还很难,是应该读出来用其它语言来做,有时为了性能还要在数据库上用底层的程序语言加写 UDF 来做。数据库在家里的时候,我们确实常常这么干,这会导致架构和技术栈复杂化,但家里只有自己这一个用户,自己说了算,问题并不突出。

现在数据库在云上了,就不是忍受一下架构和技术栈复杂化的问题了。和家里不同的是,云是公用的,不能有太多的个性化。用户不能熟悉什么用什么,而是云提供什么就用什么。云数据库通常只提倡使用 JS 这种能简单部署的解释性语言作为 SQL 的延伸,这不会对运维造成较大负担,但 JS 的功能和性能都比较差,只是聊胜于无(SQL 处理某些事实在太烦了)。如果开放 Java/C++ 这种编译型语言接口(UDF 常常要用这种语言来写),就相当于每个用户有一套自己的独特数据库引擎,这种场景下的运维会变得异常复杂(严重加剧前述元数据加载以及 VM 启用和复用的困难)。也不是做不到,但还是会推高成本和加大风险。

其实这个我们都知道的问题,数据仓库云服务商也知道,所以有些服务商也在积极地在 SQL 中深度融入 Python 的能力,但这两套风格迥异的东西是不是能融合好,拭目以待吧。

现在的结果,大概率你在云上还是要靠 SQL 搞定所有事情。于是,还真有牛人用 SQL 硬是写出了漏斗分析。

写是都写得出来,SQL 的计算能力在理论上是完备的(加上存储过程),但需要什么级别的高手呢?开发成本会有多高呢(SQL 调试还一直挺困难)?我们用云是为了省事继而省钱,开发人员的时间恐怕更值钱吧,一个个工资都挺高的。而且,这样写出来的代码,真地过两月自己都看不懂,维护起来也难,又是成本。

SQL 语言能力不足,还表现在难以实现很多低复杂度算法。比如电商中经常要做的用户去重计数,如果数据有序,则可以用很小内存高速计算出来。但 SQL 的理论体系不保证数据存储的有序性,也写不出这种利用有序的计算逻辑,就只能指望数据库的优化器了。而这种嵌套多层绕来绕去的 SQL 语句通常会把优化器搞晕,数据库只能采用保守的高复杂度算法。比如去重计数通常要保持住已遍历过的键值,还要计算 HASH 值来比对,计算速度慢且 CPU 和内存资源消耗都多,然后就只能多花钱买计算资源了。

SPL 的语言能力就要完善得多,不仅拥有上述例子中需要序运算能力,还提供了很多包括矩阵、拟合甚至 AI 建模的函数,绝大多数数据任务都可以在 SPL 体系内轻松完成,无需再借助其它语言,也用不着写 UDF,架构简单很多,技术栈单一。

SPL 的代码也更简单,复杂的任务也只要按自然思维写出代码就行了,不像 SQL 那样绕。开发成本就会大幅降低(SPL 调试器好用很多),代码简短易读,维护也就不难。当然,需要程序员经过一定的训练以掌握 SPL 的概念。

SPL 还易于实现低复杂度的代码,从而获得最快的执行速度,这意味着消耗的硬件资源更少,也就是应用成本更低。比如 SPL 就可以利用有序存储在较小内存下高性能实现用户去重计数,速度快且消耗资源更少。

而且,有了强计算力后,大部分用户的大部分任务都不必使用集群了,稍强一点的 VM 就可以搞定。这也会让运维变得简单很多,把有限且昂贵的资源都尽量用到计算上。

云上的资源虽然基本上是无穷的,但用户口袋里的钞票肯定是有穷的。其实,从成本上看,云上的资源并不便宜,特别是多租户时的计算资源(CPU 和内存),远远不能说是无穷。

SQL 的优势

看起来,相对于 SQL,SPL 就没有劣势?

这当然不可能,否则就不客观了,这世界上没有全面都好的东西。

SQL 经过几十年的积累发展,很多数据库都拥有很强的优化引擎。对于适合用 SQL 完成的简单场景运算,可以将普通程序员写出来的慢语句优化出较好的性能,从这个意义上讲,对程序员的要求相对较低。某些场景(比如多维分析)已经被优化多年,某些 SQL 引擎也可以跑出相当好的极致性能。

相比之下,SPL 没有做多少自动优化的功能,要跑出高性能,几乎全靠程序员写出低复杂度的代码。程序员需要经过一定的培训和练习来熟悉 SPL 的理念和库函数,多一个上手的门槛。而且 SPL 目前是用 Java 实现的,虽然获得了易于云化的好处,但也受限于 JVM 而无法充分利用 CPU 和内存。某些简单运算场景下的性能还是赶不上被充分优化的 SQL 引擎。

SPL 云

现在我们可以来总结性地描述和比较一下基于 SPL 和 SQL 的云数据仓库了。

SPL 云在架构上更轻,带来管理简单、高复用率、低出错率,获得低运维成本,不需要巨大规模就能打平运维成本;SQL 云太重,通常需要巨大规模后才能摊薄运维成本。

SPL 的语言能力更易于实现复杂逻辑的高性能算法,降低开发成本和减少硬件资源,用户消费会低很多;SQL 只能在简单场景获得低成本,面对复杂计算需求时用户消费难以控制。

因为存储很便宜,可以用冗余数据同时启用 SQL 云和 SPL 云,SPL 云接管 SQL 处理起来成本过高的任务,把 SQL 适合的任务留给充分优化过的 SQL 引擎。两种云各自处理各自有优势的需求,混合使用后能大幅降低用户的总成本。

SPL 的开放计算能力,能使数据整理准备(ETL)更直接高效,甚至可以用来为 SQL 云准备数据(将原始数据处理好后写入 SQL 云)。

利用 SPL 的开放计算能力,还可以解决 HTAP 需求。用户不需要将 TP 业务迁移到新的 HTAP 数据库(这会面临较大的风险),仍然是定期将冷数据整理进 AP 数据库(也可以直接用 SPL 云充当),由 SPL 来实现 TP 数据库和 AP 数据库的混合运算。由于 TP 数据库中的热数据量较少,临时读取计算的压力也不会太大了,AP 数据库则可以精心整理以获得更高的运算性能。而单一的 HTAP 数据库一般来不及对大量的 AP 数据做复杂的整理准备,整体的运算性能会更差。

从 TP 业务继续想,SPL 云还可以用作数据微服务云。SPL 有完善的语言功能(分支、循环、子程序都有),可以实现非常复杂的业务逻辑。一个个 SPL 脚本就是一个个“微服务”,前端应用请求服务,云端执行脚本返回结果就行了,需要访问 TP 数据库或其它数据源都可以在脚本中实现。利用云存储还可以在云端缓存中间数据,应用开发只要关心界面就完了,数据处理服务都可以交给 SPL 云。

把 SPL 云构架在成熟的大型云存储上,可以实现真正的湖仓一体。未规范化的数据也可以先扔进“湖”中被 SPL 计算,需要高性能时再整理优化成“仓”,湖仓建设可以循序渐进。SQL 的数据组织机制无法接受不规范的数据,有“仓”无“湖”,还需要借助其它技术配合才能实现数据湖,而且也很难湖仓一体。

说得这么热闹,SPL 云其实还在路上,这些也还是思考和展望。从软件到云服务,还有不少工作要做,这是 SPL 团队下一步的重点工作内容,期待我们早日把 SPL 云推出来。

最后再做个类比:

SQL 更像火车,有复杂的管理和调度体系,事先规划线路并做优化,在某些固定线路上可能跑得快且容量大,乘客只要买票不必关心驾驶。但面对灵活复杂的需求则非常笨拙低效。

SPL 更像汽车,没有管理调度体系,可灵活高效地应对复杂需求,乘客即司机需要自行设计合理的行程方案,还需要经过一定驾照训练。但处理某些固定线路上的大容量运输时可能会弱于火车。

汽车需求应该是远大于火车需求,但并不能完全替代火车。