数据计算引擎 esProc SPL(2024)

esProc SPL 作为数据计算引擎,具备低代码高性能轻架构全场景4 个主要特点,后面的内容我们会详细讲解。

esProc 是什么?

首先我们来了解一下 esProc 是什么?


esProc SPL 是一款面向结构化和半结构化数据的计算和处理引擎,可以用做分析型数据库和数据计算中间件。主要应用于线下跑批和在线查询两个数据分析型应用场景。不过,与绝大部分产品不同,esProc 没有基于 SQL 体系,但也不是常规意义的 NoSQL 技术,而是独创了 SPL 语法,相对现有技术不仅编码更简单,运行效率也更高。


具体能解决哪些问题呢?

作为全功能计算引擎,可以面向所有结构化数据计算场景,但感受最明显的主要是在线查询和线下跑批时遇到的性能问题。

现在很多行业都有跑批业务,一般都是晚上业务空闲的时间做,因此会有一个固定的时间窗口,要在这个时间段内做完才行,否则就会影响业务。但随着业务的积累跑批的压力会越来越大,时间有限但业务和数据量越来越多,有时就会出现跑批跑不完的情况,月末年终这种现象更明显,担惊受怕的。

还有查询报表,总有几张比较重要的查起来很慢,三两分钟甚至更长时间,优化几轮效果也不明显,导致用户拍桌子,业务不满意。有时查询人数一多,选择的时间跨度一大,就更查不出来了。

现在数据库的压力也大,经常面临扩容压力。单体搞不定时还要上集群,不仅成本高,运维也更复杂。很多时候如果能提升性能,集群可能就不需要了,但现在却是遍地分布式。

还有很多场景我们就不一一举例了,esProc 就是专门为这些数据分析型场景服务的。


当然,esProc SPL 面向的场景现在也都有相应技术在处理。对标的技术最主要的一类是采用 SQL 语法应用于 OLAP 场景的数据库和数据仓库。如常规的 MySQL、PostgreSQL、Oracle、DB2 等关系型数据库;还有 Hive、Spark SQL 等 Hadoop 体系的数据仓库;以及新兴的 MPP 数据仓库和云数据仓库,如 Snowflake 等;还有一类商用数据库一体机,像 Oracle 的 ExaData。

从开发语言的角度来看,除了 SQL 外,SPL 还可以替代一些数据计算技术。如 Python,Scala,Java,Kotlin 等。

esProc SPL 相对这些技术更具备低代码、高性能、轻量级、全功能等特点。SPL 在实施计算尤其是复杂计算时更简洁,比 Python、SQL 这些都要简单,也就是更低代码;esProc SPL 提供了大量高性能算法以及高性能存储可以达到更快的计算速度;esProc SPL 可以独立使用也可以集成嵌入,还可以基于多种数据源直接计算,具备更加轻量开放的特性;SPL 除了提供常规运算能力,还提供了很多包括矩阵、拟合甚至 AI 建模的函数,绝大多数数据任务都可以在 SPL 体系内轻松完成,功能更加全面。


esProc 能给用户带来哪些价值呢?主要是性能和成本两方面。
性能会提升多倍,可以让跑批任务提前完成,从容应对后续任务;也可以让查询报表秒出,优化用户体验;还可以把原来预计算这种不灵活的方式改为更灵活的实时计算,改变业务模式。

性能提升还意味着成本减少。原来需要小集群现在用单机就可以,原来用大集群现在用小集群;而且 esProc 不挑硬件,与普通的文件系统和低费用云存储都能跑出高性能,使用成本显著降低。

案例简析

下面我们来看看 esProc 实际的案例效果。


这是国家天文台的一个聚类计算任务,要从多张天体照片中按一定规则匹配出相同天体并做聚合运算。11 张照片,每张 500 万个天体,每个照片都要跟另外 10 张照片比对,计算复杂度是:500 万 * 500 万 * 10=250 万亿次比对。由于计算量太大,技术验证时只能先基于 50 万天体测试:Python 代码写了 200 行,跑了 6.5 天,这根本不现实;用某知名的分布式数据库动用 100CPU 的集群算了 3.8 个小时,也还是太慢。要知道 500 万天体计算量要大 100 倍。

这个场景最终用 esProc SPL 来做,代码写了 50 行,利用二分法初筛再计算,50 万天体只需要 2.5 分钟,全部 500 万天体也只用了 3 个小时,速度提升了 2000 倍左右。
案例详情: SPL 提速天体聚类任务 2000 倍


这个案例也是一个跑批场景,某银行用 AIX 小机 +DB2(银行的标配)跑批,其中一个“对公贷款协议明细”存储过程运算时间需要 1.5 小时。这个计算涉及 48 个 SQL 步骤,十分复杂的多表关联,代码量有 3300 行。由于这个跑批任务是整个银行跑批任务的一个环节,这个环节慢就会拖累整体跑批过程,急需优化。

用 esProc SPL 来做 10 分钟就可以完成,提速了 8.5 倍,代码量从 3300 行降到 500 行。这里主要利用了 SPL 的有序计算、遍历复用等特性。
案例详情: 开源 SPL 提速银行贷款协议跑批 10+ 倍

spl20249png
电商漏斗需要统计在指定时间窗口按指定次序发生多次事件中前 N 个的用户数,以便计算用户流失率为营销动作提供依据。这个案例中数据规模接近 4 亿行,3 步漏斗用 SQL 在 Snowflake 的 Medium 级服务器(相当于 32 核)上 3 分钟未跑出结果,而用户期望不超过 30 秒。

esProc SPL 利用有序计算能力,单机(16 核)在 10 秒内就能完成,远超用户预期。并且 SPL 编写的代码更为通用,可以处理任意步骤的漏斗计算(SQL 则要不断增加子查询)。
案例详情: SPL 优化电商漏斗分析从 3 分钟 + 到 10 秒


银行贷款业务涉及的指标数量很多,像贷款余额、担保类型、客户类型、放款方式等等,数百个指标之间相互组合形成庞大的计算规模,而且伴随高并发进一步加剧计算难度。这个场景计算过程中需要对 2000 万行大表及更大的明细表关联、过滤、汇总计算,每个页面涉及近 200 指标计算,10 并发共 2000 多指标同时计算。如此庞大的计算规模只能提前一天使用 Oracle 预计算的方式完成,但预计算又无法满足业务需要。

使用 esProc SPL 改造时借助遍历复用,一次遍历完成多个指标计算,完全满足实时计算的性能需要,10 并发共 2000 指标计算不到 3 秒。数据无需预先计算,临时选择任意标签组合,实时查询结果。
案例详情: 开源 SPL 优化银行预计算固定查询成实时灵活查询


这个银行建设有中央数据仓库,但由于中央数据仓库承担全行的数据任务压力很大,所以只能分配给 BI 系统 5 个并发,无法满足需要。

所以要解决这个问题就需要搭建一个前置数据库专门为 BI 系统服务。但使用数据库搭建时面临一个问题,如果仅把高频使用数据从数据仓库导入前置机当涉及查询其他数据时就查不到,无法响应业务需求;如果把所有数据都导入前置机又不现实,这相当于重新建设一个数据仓库,代价太大。

最终使用 esProc SPL 来搭建前置库,仅把高频数据导入即可,这样可以避免重复建设。esProc SPL 承担绝大多数的高频计算任务,剩下少量低频任务通过 esProc SPL 自动路由到中央数据仓库由数据仓库响应,这样就解决了前面提到的两个问题。这里的关键是 esProc SPL 提供的自动路由功能。
案例详情: 开源 SPL 提升银行自助分析从 5 并发到 100 并发

esProc 凭什么?

从上面的案例,我们可以看到, SPL 的表现不错。那么大家肯定要问,为什么?SPL 有什么过人之处吗?那些数据库厂商都不会这些技术吗?
再回顾一下刚才的案例会发现,SPL 对标的原有技术大都是关系数据库和 SQL。也就是说,在代码效率和运算性能两个方面,SPL 都比 SQL 有非常明显的优势。

这样,其实刚才的问题可以反过来问,不是 SPL 为什么做得更好,而是 SQL 为什么做得不好。

先看 SQL 为什么这么难写。这个例子是要计算一支股票最长连涨了多少天?

select max (consecutive_day)
from (select count(*) (consecutive_day
      from (select sum(rise_mark) over(order by trade_date) days_no_gain
            from (select trade_date,
                         case when closing_price>lag(closing_price) over(order by trade_date)
                              then 0 else 1 END rise_mark
                  from stock_price ) )
      group by days_no_gain)

SQL 采用了这样嵌套 4 层的写法,整体比较绕。这道题曾经作为我司的招聘考题,通过率不足 20%;因为太难,后来被改成另一种方式:把 SQL 语句写出来让应聘者解释它在算什么,通过率依然不高。这说明什么?说明情况稍有复杂,SQL 就变得即难懂又难写!

其实这个计算很好解,只要按交易日排好序然后得到一些连涨连跌的区间,最后数一下最大连涨区间的天数就行了,很简单。但是 SQL 对有序运算支持不足,未直接提供有序分组,只能采用迂回嵌套的方式,既难懂又难写。而这个计算并不是多难碰到的罕见问题,我们实际业务中比这复杂的情况比比皆是,那些上千行的 SQL 都在解决这类难题。

再来看 SQL 跑不快的问题,还是举例,从 1 亿条数据中取前 10 名。

SELECT TOP 10 * FROM Orders ORDER BY Amount DESC

这条语句并不复杂,但有个 ORDER BY 字样,这意味着要对所有数据进行大排序,然后再取出前 10 个。大数据排序很慢,会涉及多次内外存交互,如果按照表面的意思去执行效率会很低。其实这个计算有更快的方法不需要全排序:始终保留一个 10 个最大成员的集合遍历一次就能算完,但 SQL 却无法描述这样的计算。这时候只能指望数据库的优化器了,对于这种简单取前 10 条的情况,大部分数据库都会在工程上优化,并不会真排序,就可以很快地计算出来。但如果计算变得复杂优化引擎就会犯晕最后只能执行慢算法了,像下面那种求组内前 10 名。

SELECT * FROM (
   SELECT *, ROW_NUMBER() OVER (PARTITION BY Area ORDER BY Amount DESC) rn
   FROM Orders )
WHERE rn<=10

这个 SQL 和前面从全集里取前 10 名的写法有很大差异了,要使用子查询和窗口函数这样“绕”的方式才能实现,这样复杂的情况数据库优化引擎也不会优化了,只能去执行排序,最后变得很慢。实际测试中发现,Oracle 计算组内 TopN 要比全集 TopN 慢几十倍,本来只多个分组性能应该只下降一点点,但结果和我们想象的差距很大,这说明 Oracle 在计算组内 TopN 时大概率做了排序导致性能陡降,优化器也不起作用了。

那 SPL 是怎么做的呢?

计算股票最长连涨天数:

Stock.sort(TradeDate).group@i(Price<Price[-1]).max(~.len())

利用 SPL 提供的有序分组,一句就写完了。这个实现逻辑与前面的 SQL 完全一致,但表达起来简洁得多。

求组内 TopN:


A


1

=file(“data.ctx”).create().cursor()


2

=A1.groups(;top(-10,amount))

金额在前 10 名的订单

3

=A1.groups(area;top(-10,amount))

每个地区金额在前 10 名的订单

SPL 将 TopN 视为返回集合的聚合运算,避免了全排序;全集和分组时写法基本一样,都不用绕来绕去。
很多时候,写得简单和跑得快其实是一回事,代码写的简单跑得就快,反过来如果写的太复杂也就没法跑快了。

我们再看一下前面提到的漏斗分析案例。电商要分析用户在平台浏览商品、加入购物车、提交订单、付款等步骤的流失率。这里碍于篇幅展示了一个三步的漏斗计算。

with e1 as (
 select uid,1 as step1,min(etime) as t1
 from event
 where etime>= to_date('2021-01-10') and etime<to_date('2021-01-25')
 and eventtype='eventtype1' and …
 group by 1),
e2 as (
 select uid,1 as step2,min(e1.t1) as t1,min(e2.etime) as t2
 from event as e2
 inner join e1 on e2.uid = e1.uid
 where e2.etime>= to_date('2021-01-10') and e2.etime<to_date('2021-01-25')
 and e2.etime > t1 and e2.etime < t1 + 7
 and eventtype='eventtype2' and …
 group by 1),
e3 as (
 select uid,1 as step3,min(e2.t1) as t1,min(e3.etime) as t3
 from event as e3
 inner join e2 on e3.uid = e2.uid
 where e3.etime>= to_date('2021-01-10') and e3.etime<to_date('2021-01-25')
 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.uid = e2.uid
 left join e3 on e2.uid = e3.uid

我们看到 SQL 由于缺乏有序计算且集合化不够彻底,需要迂回成多个子查询反复 JOIN 的写法,编写理解困难而且运算性能非常低下,很难优化。这里是三步漏斗,如果增加步骤还要增加子查询,难度可见一斑。

再看 SPL 的代码:


A

1

=["etype1","etype2","etype3"]

2

=file("event.ctx").open()

3

=A2.cursor(id,etime,etype;etime>=date("2021-01-10") && etime<date("2021-01-25") && A1.contain(etype) && …)

4

=A3.group(uid).(~.sort(etime))

5

=A4.new(~.select@1(etype==A1(1)):first,~:all).select(first)

6

=A5.(A1.(t=if(#==1,t1=first.etime,if(t,all.select@1(etype==A1.~ && etime>t && etime<t1+7).etime, null))))

7

=A6.groups(;count(~(1)):STEP1,count(~(2)):STEP2,count(~(3)):STEP3)

由于提供了有序计算且集合化更彻底,代码直接按自然思维写出即可,简单且高效。而且这段代码能够处理任意步骤数的漏斗,只要改变参数即可,十分通用。

这是个实际案例的简化版(原 SQL 有近 200 行),用户使用 Snowflake 的 Medium 级服务器(相当于 4*8=32 核)3 分钟没有跑出来;而 SPL 代码在一个 16 核的 GCP 服务器上仅用 10 秒就跑出来了。


现实业务中,这些 SQL 搞不好的场景比比皆是。
像上面计算流失率这种有序计算,因为事件在指定时间窗口内完成、按指定次序发生才有效。用 SQL 描述这种跟次序相关的复杂计算很繁琐,性能低很容易把数据库跑崩,极难优化。

还有大数据下的多指标计算,像用户画像、碰撞分析,由于 HASH JOIN 算法复杂度高,占用内存大,SQL 计算速度很慢,也容易跑崩,经常只能借助宽表,往往不能满足业务需要。

前面案例中的大数据量复杂多步骤跑批任务,有些复杂过程需要借助游标完成,游标读数计算很慢,而且没法并行,浪费计算资源。多步骤计算过程还会伴随中间结果反复落地,效率极低。

这些场景用 esProc 来做,改善效果十分明显。


为什么 SPL 可以写得更简单而且跑得更快呢?

我们知道,软件改变不了硬件的计算性能,CPU 计算 1 亿次就需要那么多时间。但我们可以想办法设计出高效率低复杂度的算法,让硬件少执行一些基本运算,每个步骤都少一点,整体节约的时间就非常可观了。
不过,算法只想出来还不行,还要能实现,也就是写出代码。但传统数据库受限于理论体系,用 SQL 很难写出高性能算法,面临“想出来起不出来”的尴尬局面。
而 SPL 就是帮助你不仅能想出高性能算法,还能实现,而且还能很简单地实现,这样性能自然就上来了。


我们可以再做个类比,要计算 1+2+3+…+100。普通人拿到题就开始 1+2=3,3+3=6,6+4=10,…… 这么一直算下去;但高斯通过观察发现 1+100=101,2+99=101,一共有 50 个 101,最后 50*101=5050 就很快算完了。这个故事相信大家都不陌生,我们会感慨高斯小朋友很聪明,但大家很容易忽略另外一件事情,那就是高斯那个年代已经有了乘法,我们知道乘法是晚于加法发明出来的,如果没有乘法即使高斯再聪明也没办法那么算了。SQL 就像只有加法的算数体系,要解决连加这样的问题就只能一个一个累加,代码冗长计算低效;而 SPL 则相当于发明了乘法,书写简单性能也更高。

SQL 的困难源自关系代数,这种理论上的缺陷无法通过工程优化来弥补;SPL 基于完全不同的“离散数据集”体系,在理论上就提供了更丰富的数据类型和基础运算,因此拥有更强大的表达能力。

SPL 就像在加法的基础上增加了乘法的计算体系,其实 SPL 中还有很多乘法。这里列出了部分 SPL 算法,包括遍历技术、关联计算、高性能存储以及分布式计算等,其中加星号的都是 SPL 的独创发明。


那么 Java 为什么也不行?
Java 由于过于原生缺少必要数据类型和计算类库导致计算都要从头实现很繁琐。像分组汇总用 Java 实现就需要十几行代码,虽然 Java8 提供的 Stream 一定程度地简化了这类运算,但复杂一点的计算仍然十分困难。

对于性能要求高的计算,Java 写起来就更难。像不用大排序的 TopN 运算、性能更好的 HASH 连接,以及利用有序进行有序归并等。这些算法本身实现就很有难度,加之 Java 的类库缺乏导致很多应用程序员并不会,经常不得不采用相对简单的慢算法,最后连 SQL 都跑不过,还怎么解决这些问题。

大数据的运算性能很大程度上还和数据 IO 相关,如果数据的 IO 成本太高,运算再快也没用。高效的 IO 经常依赖于专门优化的存储方案,但遗憾的是,Java 没有应用较广泛的高效存储方案,一般会使用文本文件或数据库存储数据,数据库的接口效率性能很差,文本虽然好一点,但又会在数据类型解析上消耗过多时间导致性能仍然不高。

如果再加上工程上的难以热切换、紧耦合等缺点,Java 与 SQL 相比尚且不足,更别说超过 SQL 去解决前面的那些问题了。


Python 为什么还不行?

通过 Java 的比较我们基本能感受到 Python 的缺点很多是类似的。比如相对复杂一点的计算实现困难,像相邻引用、有序分组、定位计算、非等值分组等做起来都没那么简单。

对于大数据计算又没提供相应的外存计算机制,导致大数据能力差。而且, Python 的并行是伪并行,对于 CPU 来说就是串行,甚至比串行还慢,难以充分利用现代 CPU 多核的优势。

Python 无法在进程内使用简单的多线程并行机制,很多程序员只能采用复杂的多进程并行,进程本身的开销和管理复杂得多,并行程度无法和多线程相提并论,加上进程间的通信也很复杂,有时只好不直接通信,用文件系统来传递汇总结果,这又导致性能大幅下降。

与 Java 一样,Python 也没提供高效的存储方案用于高性能计算。只能借助开放文件或数据库,性能很低。很多时候,Python 也会和 SQL 结合使用,一样解决不了 SQL 面临的那些问题。再加上 Python 的版本问题、集成性问题等原因,Python 真的也不行。

技术特性

前面我们解释了 esProc SPL 写得简单和跑得快的原因,也就是 SPL 的低代码和高性能。
下面我们来具体看一下 esProc SPL 的技术特性。


esProc 目前是纯 Java 软件,只要有 JDK1.8 及以上版本的 JVM 环境的任何操作系统都可以运行,包括常见的 VM 和 Container。

esProc 正常安装后占用空间不到 1G,但绝大多数都是引用的第三方外部数据源驱动包。其核心包不足 15M,甚至可以在 Android 上运行。

除 JVM 外,esProc 对运行环境没有其它硬性要求。对硬盘和内存的容量要求和计算任务相关,不同计算任务相差很大。执行同样计算任务时,esProc 需要的硬件资源通常小于传统数据库。加大内存、选用更高主频和核数的 CPU 以及使用 SSD 对提升计算性能会有提升作用。


esProc 由 IDE、SRV(Server)、JDBC、Connectors(Native Connector 和 External Connector Library)构成,相互之间的关系如图示。黄色箭头连线代表数据流向,IDE、SRV、JDBC 通过 Connectors 读 / 写数据源数据。IDE 编写的 SPL 脚本(Script)在 IDE 端编辑调试,在 SRV(服务端)和 JDBC(应用端)运行。


esProc 的运行模式有两种。一种是嵌入运行模式,在无 Server 的情况下嵌入到应用中,作为应用的一部分,随应用运行。有别于常见 JDBC 仅提供的接口能力,esProc JDBC 还具备完善的计算能力,可以作为嵌入式计算引擎在应用内部提供强计算能力,表现更加轻量灵活。


另一种是独立运行模式,需要部署独立的 Server,应用通过 JDBC 等接口与 Server 交互。独立运行模式支持集群,提供负载均衡和容错机制,适合计算规模较大的场景。


在开发上,esProc 支持本地和远程开发。本地开发脚本编辑调试均在本地进行,运行时数据需要传输到本地计算。
出于某些安全性或云环境等因素的考虑,esProc 还提供远程开发模式。使用远程开发前需要事先部署远服务器 RSRV,本地 IDE 连接 RSRV 进行开发调试,脚本运行和数据传输均在远端完成,IDE 仅显示计算结果,供调试使用。


esProc IDE 提供了丰富的编辑调试功能,单步执行、调试执行、设置断点、执行到光标等,同时 SPL 的过程化语法支持分步编码,每步的运行结果都可以通过右侧的结果面板实时查看,更容易定位问题。
由于 IDE 本身也具备独立的计算能力,因此可以直接用于桌面分析,覆盖原来使用 Excel、Python 处理数据的能力。


esProc 可以处理多源数据,数据可以分布在本地或远程,但对 esProc 来说这些数据源都是逻辑等同的。esProc 不拥有这些数据,数据在哪都能计算,存储和计算不绑定,天然支持存算分离。


esProc 针对不同数据源提供了不同的接口,比如 RDB 的 JDBC、WebService 的 RESTful、文件接口、以及其他数据源的可扩展外部库,使得 esProc 可以从容应对多样性数据源。更进一步,通过这些接口转换后都会形成 esProc 统一数据对象:序表或游标,基于统一数据对象进一步实施遍历、关联等运算,与处理单源数据一样,天然适合完成多源混合计算。


目前 esProc 支持的数据源种类很多, RDB、NoSQL、时序数据库、Hadoop、WebService 以及云上对象存储等等都可以直接使用,数据实时性更好,还可以充分保留多样数据源自身的优势。
特别地,esProc 对 json,xml 等多层结构化数据有强大的支持能力,远远超过传统数据库。所以 esProc 可以很好地和 mongodb 以及 kafka 等类 json 数据源配合,也能方便地和 HTTP/Restful 以及微服务交换数据并提供计算服务。
esProc 还能方便地计算 Excel 文件中的数据,但不擅长处理 Excel 的格式。esProc 也不擅长处理图像音频和视频等数据。


SPL 是专门设计的语法体系,天然支持分步尤其适合复杂过程计算。支持循环、分支、过程、子程序等完整的编程能力。在每步运算中可以使用单元格名引用上一步计算结果,无需定义变量(当然也支持变量)。

同时 SPL 提供了非常丰富的结构化数据计算类库,针对字符串和日期时间的处理、数学计算、对文件和数据库的读写操作、对 JSON/XML 多层数据的支持、分组 / 循环 / 排序 / 过滤 / 关联 / 集合运算 / 有序计算一应俱全,特别针对序列(序表)提供的循环函数可以极大简化集合运算,还有针对大数据计算提供的游标,为了减少硬盘重复遍历的管道,以及并行和分布式计算的支持。此外,还提供针对 AI 的建模和预测函数,对包括 MongoDB、Elasticsearch、HBase、HDFS、Influxdb 等几十种数据源在内的外部库函数等等。

目前 SPL 提供了 400 多个函数,叠加每个函数包含数个选项相当于几千个库函数,再结合过程、循环、分支等完善的程序语言功能可以完成全面的数据处理任务,这是全功能特点的典型表现。

esProc 的计算能力全部由自身内部提供,不依赖第三方,尤其 SPL 不会翻译成 SQL。从能力上来看,SPL 是 SQL 的超集,并且拥有更简洁的语法和更高的计算性能,二者理论基础完全不用,翻译动作既无必要,也无可能。


esProc 在与 RDB 交互时提供了两个增强能力。

鉴于不同 RDB 的 SQL 语法各有不同,方言问题会导致应用开发繁琐,不同数据库之间移植困难,程序通用性降低。esProc 提供了 SQL 转换功能,可以将标准 SQL 转换成不同数据库的语法,应用开发时只需要编写标准 SQL 即可,程序通用性大幅增强。

RDB 的 JDBC 效率很低,基于 RDB 计算往往会面临 IO 瓶颈,取数成本远远超过计算成本。esProc 提供了并行能力,可以启动多线程并行取数,加快数据读取效率,减小 IO 开销。


我们知道,不同数据源的读写性能差异很大,其中 RDB 几乎最差,而文件最好。因此在涉及高性能计算时,esProc 推荐使用文件存储,以避免过高的 IO 成本。esProc 还特别为远程文件系统,如分布式文件系统或云上对象存储设计了缓存功能,用户可以在使用时选择缓存数据来获得更高计算性能。


esProc 提供了自有的高效数据文件存储,私有数据格式性能更高,还可以按照文件系统树状目录方式按业务分类存储数据。

目前 esProc SPL 提供了两种文件格式,集文件和组表。

集文件是一种基础二进制数据格式,采用了压缩技术(占用空间更小读取更快),存储了数据类型(无需解析数据类型读取更快),还支持可追加数据的倍增分段机制,利用分段策略很容易实现并行计算提升计算性能。

组表提供了更复杂的存储结构,支持行列混合存储,有序存储可以进一步提高压缩率和定位性能,支持更高效的智能索引,支持主子表合一有效减少存储与关联,同时支持倍增分段机制更容易并行提升计算性能。


esProc 没有传统数据仓库中“库“的概念,没有元数据概念,不对某个主题的数据进行统一管理。对 esProc 来讲,数据没有“库内”和“库外”的区分,也没有明确的“入库”和“出库”的动作。

任何可访问到的数据源都可以看作 esProc 的数据,并可被直接计算。计算前不需要先“入库”,计算后也可以用接口写出目标数据源中,不需要刻意“出库”。

esProc 对常见的数据源都封装了访问接口,各种数据源在逻辑上地位基本相同,不同之处仅仅在于访问接口以及不同接口表现出来的性能,这些接口是数据源厂商提供的,esProc 无法干预其功能和性能。

esProc 设计了特殊格式的文件(集文件和组表)来存储数据以获得更多的功能和更好的性能,这些数据文件存放在文件系统中,esProc 在技术上并不占有这些数据文件。esProc 已经将文件格式公开(访问代码开源),可以被任何能访问到这些数据文件的应用程序按照公开规范(或基于开源代码)读写,当然更方便的是直接使用 SPL 语写。

从这样意义上讲,esProc 与外部的数据交换没有“入库”“出库”的动作,但可能会有“转换”的动作,即把外部数据转转换成 esProc 格式的文件以获得更多功能和更好性能,也可以把 esProc 格式的文件转换成外部数据供其它应用继续使用。这些转换工作都可以使用 SPL 完成。

esProc 原则上并不管理数据,也不对数据的安全负责。一定程度上可以说,esProc 没有也没必要有安全机制。

持久化数据的安全性原则上数据源本身负责。对于 esProc 格式的数据文件,很多文件系统或 VM 都提供了完善的安全机制(访问控制、加密等),可以直接利用。esProc 的云版本也支持从 S3 等对象存储服务上获取数据再计算,也可以利用它们的安全机制。

嵌入式的 esProc 和主 Java 应用是同一个进程,仅向主程序提供计算服务,没有外部服务接口,不存在安全和权限问题。独立服务进程的 esProc 使用标准的 TCP/IP 和 HTTP 通信,可以被专业的网络安全产品监控和管理,具体安全措施将由这些产品负责。

esProc 专注于计算,对持久化存储的可靠性也不负责,这些方面同样的专业的技术和产品,esProc 尽量使用标准的规范,从而可以和这些技术和产品配合工作。比如可以将数据持久化到高可靠的对象存储上,esProc 实现了这些存储方案的接口,可以访问这些数据源实施计算。

esProc 是专业的计算技术,不拥有专业的安全能力,esProc 的理念是和其它专业技术配合。


esProc 没有元数据,支持存算分离,可以很容易实施弹性计算。具体应用时,需要在应用内部部署 QVS 服务,用于接收并处理用户请求,管理节点 QVA 根据计算请求动态分配 QVM 计算资源从而进行弹性计算。

有了这些开放、轻量、全面、高性能的特性,就能达到前面提到的应用效果,低代码、高性能、轻架构、全场景。

应用场景

接下来我们具体看一下 esProc 的应用场景,主要包括大数据和中间件两类。


高性能的 esProc 可以作为 OLAP 数据库 / 内存数据库使用。内置的高性能算法,特别是实时关联效率比传统 SQL 宽表还快,可以有效避免宽表带来的灵活性差的问题。
由于采用了更多内存优化机制,esProc 全内存计算时也比传统内存数据库性能更高;同时支持外存计算,能够全面覆盖内存数据库功能。
esProc 支持多源混算,开放的计算体系可以实时接入生产数据源与其他数据源混合计算实现 T+0 全量查询。
SPL 过程化语法更适应复杂计算,可以很好为复杂报表等分析业务服务,单一技术栈覆盖范围更广,运维也更简单。


针对企业在数据仓库之上构建的前置数据库或 ODS 层,esProc 也可以很好满足。高性能可以满足计算性能需要,轻量级在使用上更加简单灵活。
特别地,esProc 提供的可编程计算路由,在前置层只存储热数据的情况下,根据计算需求,将计算自动路由到前置层或数据仓库,从而实现全量数据计算。
而全面的计算能力、过程化敏捷语法又可以满足任意复杂的计算需求,在 esProc 中就能完成所有数据处理工作,全面避免应用层编程,进一步降低开发运维难度。


esProc 非常擅长完成复杂多步的跑批任务,应用于跑批或 ETL 场景。借助 esProc 的开放能力数据不需要入库直接就能算,节省入库时间。SPL 支持过程计算,同一份数据集只读取一次重复使用,中间结果无需落地就能给下一步使用,节省磁盘 IO 时间。
esProc 大数据计算能力强,支持小数据量的内存和大数据量的外存计算,提供支持列存、压缩、索引等优化后的高性能存储,同时支持并行计算,进一步提升计算性能。同等硬件跑批性能经常能提升 10 倍以上。


esProc 广泛应用在数据仓库领域,开放的计算体系直接针对多样数据源计算而无需逻辑映射,全面覆盖逻辑数仓功能,而物理存储优化下高性能计算又远超传统物理数仓,完全实现物理逻辑数仓一体化。
文件存储与计算分离又天然支持存算分离,无论本地或远程文件都无需入库,直接计算,灵活自由。
esProc 擅长复杂计算,应用范围更广。SPL 的过程计算天然可以实现存储过程类的多步骤计算,而且性能更高。SPL 的可编程能力也很强,可以充分利用任务特征写出优化代码从而获得更高计算性能,全面替代新型数据库。
esProc 运算体系的硬件资源利用率很高,可以让单机发挥出集群的算力,绝大多数原本用小集群(<10)的数据库场景,esProc 用单机就可以搞定。即使一定需要集群,集群规模也会远远小于 SQL 集群,成本更低,运维也更方便。


传统 HTAP 数据库需要迁移原有 TP 库,会面临迁移风险。esProc 的开放计算能力允许继续使用现有 TP 方案,在此基础上与 AP 数据混合计算实现 T+0 全量数据查询,这样不仅可以减少迁移风险,还能保持原有数据源优势。
将冷数据整理成 esProc 高性能存储与热数据混合计算还能充分保障高性能,快速满足 AP 业务需要。

esProc 支持流批一体计算,流数据和批数据底层模型统一,单一引擎既能算流数据也能算批数据,自然也能直接进行混合计算,不必事先转为同类数据。
esProc 可以主动或被动获取不同数据源种类的流数据,具备强开放能力。轻量级引擎无需借助复杂的流计算框架,简单轻量方便运维。
SPL 支持的有序计算特别适合处理流式数据,计算效率更高,实时性更强。在丰富计算类库的支持下也容易与批数据混合计算,适应更复杂的计算任务。


冷热数据分离后,海量冷数据面临存储和使用难题,存放数据库占用空间,还要管理运维,成本太高,使用频率却很低;但不转入又无法计算。如果每次使用都临时装载数据,效率又很低,入库时间远超计算时间,使用效果大减。
esProc 可以直接基于文件计算,冷数据采用文件存储,可存放在本地文件系统、分布式文件系统、网络文件系统,或者云上对象存储,esProc 均可及直接计算,无需入库,实时发挥数据价值,用低廉存储成本提供热计算。


esProc 主动或被动获取时序数据后,将数据分成热冷温三层存储模式,内存和外存文件配合解决高频写入和大数据查询的矛盾。SPL 的有序计算特别适合处理时序数据,可以有效克服 SQL 在有序计算方面能力的不足,实现简单的同时性能也更高。
esProc 还提供了向量、矩阵、拟合、建模等数学库,用一种技术就可以处理所有计算,技术栈简单。


esProc 搭建数据微服务平台或数据中台,由于没有元数据的束缚,加之天然存算分离特性,支持无耦合弹性计算,无需借助 Docker 或虚拟机整体表现更轻。
SPL 敏捷开发又可以大幅简化 Java 开发难度,SPL 脚本解释执行,支持热切换,修改脚本无需重启应用,可以很好适应微服务平台和数据中台多变的数据需求。


使用 esProc 搭建的湖仓一体具备很强的开放性,原始数据入湖就可以直接计算发挥数据价值,数据整理同步进行以便获得更高计算性能,循序渐进建设数据湖。
原始数据和整理后数据均采用文件格式存储在文件系统或云上对象存储中,再借助存算分离、弹性计算能力实施高性能计算,充分保障数据湖原始数据的使用效率和计算性能。
SPL 完善的计算能力不需要再借助 SQL、Python 等额外技术,单一技术栈运维更简单。


作为中间件使用上,可以将 esProc 与报表应用集成,作为报表数据准备层。SPL 敏捷计算可以提升开发效率,避免复杂 SQL 和存储过程。由于 esProc 具备独立的计算能力,不依赖数据库,代码可以跨库移植,而解释执行的脚本支持热切换可以帮助报表模块与应用解耦,单独维护。
开发效率快、性能高,可以很好应对频繁变化的报表需求,低成本应对没完没了的报表。


esProc 与 Java 应用集成可以作为应用内计算引擎,实现原来的 Java 数据逻辑以及数据微服务功能,与主程序一起打包享受 Java 成熟框架的优势。SPL 完善的计算能力和丰富的计算类库可以替代原来 Stream、Kotlin、ORM 等技术,技术栈简单。脚本不依赖数据库,移植性更强;解释执行支持热切换。


esProc 天然支持过程计算,在计算类库和敏捷语法的加持下,计算实现比存储过程更简单,可视化 IDE 编写调试脚本也更方便。计算逻辑在库外的 SPL 脚本内实现,无需过多数据库权限,移植性超强。SPL 脚本借助文件系统的树状目录管理,不同应用对应不同目录,不会出现应用间的耦合性问题。


用 esProc,中间表可以移植到成本更低 I/O 性能更高的文件系统中,降低数据库冗余,为数据库减负。SPL 直接基于文件计算,性能更高。
中间表在库外采用文件系统的树状结构进行分类管理,跟随应用走,应用下线可以放心删除对应目录的中间表,不存在任何耦合不敢删的问题。


集算器天然支持多数据源混合计算,特别擅长处理 JSON 等多层数据。使用 SPL 可以在保留 TP 库的同时将冷数据外置实现 T+0 查询,这样不仅几乎没有迁移风险,原有库还可以继续利用,保留各种数据源的优势。
更进一步,将冷数据使用 SPL 高性能文件存储,还可以获得极致的计算性能。


esProc 体积小支持嵌入,很适合用于边缘计算场景。由于提供了全面计算功能,包括数学类库,大部分任务都无需借助其他组件。
简单文件存储本地实时计算,无需借助数据库,使用更简单,同时支持接驳远程大型数据源和存储装置。


esProc 可以在应用外独立进行数据清洗准备。数据源支持丰富并且一致,方便访问各种无 SQL 数据源,只要能访问就能处理。SPL 语言能力强,描述复杂运算比 Python 更简洁,开发效率更高。
支持并行计算可以处理大数据,方便性和性能远超 Python。同时具备强集成性,必要时可以转移成应用内计算,使用灵活。


由于 esProc IDE 具备独立的计算能力,同时提供结果集可视的过程计算,使得 esProc 适合用于数据科学家探索分析。
SPL 语言能力强,描述复杂运算比 SQL 和 Python 更为简捷,同时交互性更强,调试更方便。
基于独立便携的文件存储,无需数据库就可以随时分析手边数据,使用简单灵活。
并行计算可以处理大数据,方便性和速度都远超 Python。


从前面的内容可以看到,esProc 具备丰富的功能,可以应用在数据分析的多种场景下,涉及结构化数据的计算,用 SPL 都能搞定,妥妥的全栈型数据技术。

FAQ

下面是一些常见问题。

esProc 基于开源或数据库技术吗?

前面我们详细分析过现有技术,主要是 SQL 的缺点根本原因在于其背后的理论体系,如果继续基于这些理论就无法从根本上解决问题。因此,我们发明了一套全新的模型—离散数据集,基于这个模型开发出 esProc。由于这是一系列全新的内容,市面上并无相关理论及工程产品可以借鉴,因此只能从头自己开发,从模型到代码全部自主原创。

esProc 可以部署在哪里?

esProc 完全采用纯 Java 开发,因此可以部署在任何有 JVM 的环境中运行,包括但不限于虚拟机、云服务器以及容器。具体使用时,esProc 可以独立使用,也可以与应用集成。前者要运行单独的 esProc 服务,可以搭建分布式集群,后者则以 jar 包的方式完全嵌入到应用中作为应用的一部分(计算引擎)使用。

应用程序如何调用 esProc?

esProc 提供了标准 JDBC 接口,Java 应用可以直接无缝集成调用。对于.net/Python 等非 Java 应用则可以通过 ODBC/HTTP/RESTful 接口调用。

esProc 能与其他框架集成吗?

esProc 可以像传统数据库一样运行成独立服务进程,对外提供了标准的 JDBC 驱动和 HTTP 服务供应用程序调用。Java 应用程序可以通过 JDBC 发出 SPL 语句就可以执行,调用 esProc 上的脚本代码相当于调用关系数据库中的存储过程。非 Java 应用程序可以使用 HTTP/Restful 机制访问 esProc 提供的计算服务。

对于 Java 开发的应用程序,esProc 还提供了完全嵌入的方式,即在 JDBC 驱动中封装了所有计算功能,和主应用程序在同一进程内运行,不依赖于外部的独立服务进程。

因为 esProc 是纯 Java 软件,也可以嵌入式运行,所以可以完全无缝地集成进各种 Java 框架和应用服务器中,比如 Spring,Tomcat,…,可以被这些框架调度和运维,对于这些框架而言,esProc 的逻辑地位和用户写的 Java 应用程序完全相同。

需要指出的是,对于计算型框架(比如 Spark),虽然 esProc 能被无缝集成,但并没有实际意义。esProc 要求把数据转换成 SPL 特有的数据对象才能实施计算,不仅转换消耗时间,而且原计算框架中的数据对象都将失去意义,两类数据对象的优点不能融合。这些计算框架的关键点主要就是其数据对象(比如 Spark 的 RDD),如果不能继续使用,则计算框架本身也将失去意义。esProc 的计算能力远远超过常见的计算框架,也没有必要再使用这些框架。

特别地,对于流计算框架(比如 Flink),esProc 即使能集成也不能发挥作用。esProc 独立服务过多次流式计算案式,完全不需要流计算框架的支持,完成同样计算量消耗的资源通常会比这些流计算框架低一个数量级,而且功能更丰富。

esProc 能基于现有数据库或其他数据源工作吗?

esProc 提供了多种数据源支持,数据库、文本、excel、json/xml、webservice 等几十种数据源,数据库当然也不例外, esProc 可以完成数据库与其他数据源(如文本)的关联混合运算。esProc 直接使用数据源本身的接口和语法,不需要将数据源映射成关系数据库表。

不过,对于数据密集型任务(大数据时代的大部分场景)由于数据库 I/O 性能不佳,数据从数据库读出会消耗大量时间,即使最后 esProc 计算的时间很短总体时间仍然很长,达不到性能要求。此外,数据库或其他数据源通常也不提供低复杂度算法需要的存储。因此对于高性能场景,需要将数据(大量冷数据)从数据库中转存到 esProc 高性能文件存储中才能获得最优性能。同时,少量热数据仍然可以存储在数据库中,借助 esProc 的多源混算能力可以轻松实现 T+0 全量数据查询。

esProc 把数据存在哪里?

esProc 采用文件存储数据,可以支持开放的文本格式,也提供了高性能的私有文件格式。文件具备更强的开放性和灵活性等特性,基于文件更容易设计高性能存储方式以及通过并行来提升运算性能。任何操作系统下的文件系统都能支持,包括本地文件系统、网络文件系统都可以使用。这样 esProc 可以天然支持存算分离,而不像数据库那样绕过文件系统直接操作硬盘导致存算分离困难。

esProc 高可用如何保障?

esProc 支持分布式计算,可以多节点配合工作,但实际应用中很少用到,因为除高并发场景外,绝大多数任务的数据量和响应期望,esProc 都可以用单机实现。

esProc 的云版本(可支持私有化部署)将支持自动的弹性计算,请求量变大时会自动启用新的 VM 实施计算,请求量变小时将自动关闭闲置的 VM。

嵌入式的 esProc 仅上主应用程序提供计算服务,不能对外提供服务,也不能负责对外服务的可靠性,这由主应用程序以及框架来负责。

独立进程的 esProc 支持热备机制,JDBC 会在当前仍可工作的服务进程中选择负担较轻的来实施计算。esProc 的分布式计算也提供了容错能力,但 esProc 设计目标不是大规模集群,计算任务过程中发现节点故障后,该任务将被宣布失败。esProc 容错程度仅到发现节点故障时还允许集群能接受新任务,仅适合小规模集群。

esProc 的服务进程目前也没有提供故障后自动恢复的功能,需要管理人员来处理,不过做个监控进程来实现这个自动功能也并不难。

esProc 云版本的弹性计算机制在分配 VM 时会避开当前失效的节点,一定程度地实现高可用性。

esProc 如何进行功能扩展?

esProc 是 Java 写的软件,提供了接口调用 Java 写的静态函数,这样可以扩充 esProc 的功能。esProc 也开放了自定义函数的接口,应用程序员可以用 Java 编写新的函数挂载到 esProc 中,使用就可以在 SPL 中使用。

esProc 有什么不足吗?

和 RDB 相比
esProc 不是 DBMS,没有传统意义上的元数据概念,数据多以文件的形式存储、管理和使用,大部分运算都要从访问数据源(文件)开始,对简单运算会比数据库麻烦一点,而复杂计算则更有优势。

和 Hadoop/MPP 相比

Hadoop/MPP 数据库集群规模相对较大(虽然 MPP 通常有数量限制),这些技术有成熟的集群使用和运维管理经验,而 esProc 的集群定位是中小规模,通常几台到几十台,即使这样 esProc 集群仍然缺少实际使用经验(相对 Hadoop/MPP 来说),在客户实际应用中经常单机就能达到甚至超越原来集群的效果,集群往往用不上,这更导致 esProc 集群的应用经验相对缺乏。

和 Python 相比

esProc SPL 目前正在发展人工智能功能,AI 建模预测等功能在逐渐完善,但与 Python 丰富的人工智能算法库相比还相差较远。

SPL 与 SQL 兼容性如何?

esProc 不是 SQL 体系的计算引擎,目前仅支持不涉及大数据量的简单 SQL,且不保证性能。在大数据需求场景下,可以认为 esProc 不支持 SQL,当然也不会和任何 SQL 存储过程兼容。

有没有将 SQL 自动转成 SPL 的工具?

鉴于 SQL 使用的广泛性,尤其针对存量系统的改造(优化)时大家很自然的想法是能否把 SQL 自动转换成 SPL 以降低迁移成本。
很遗憾,不可以。
首先数据库虽然可以作为 SPL 的数据源,但基于数据库(主要是存储)无法获得高性能,因此基于数据库无法做到二者的自动转换。更重要的是,SQL 的描述能力不足,很多高性能算法无法实施,强行将 SQL 转换成 SPL 后,只能保证功能,性能通常会差很多。

这里还要提到一点,SPL 没有提供像 SQL 那么强的自动优化机制,SQL 经过几十年的积累发展,很多数据库都拥有很强的优化引擎,碰到相对简单的慢 SQL 语句,能“猜”出其真实意图,再自动优化采用高性能方式执行(如前面讲到的 TopN);相比之下,SPL 没有做多少自动优化的功能,SPL 团队也远远没有数据库厂商那么丰富的优化经验,我们不会“猜”语句的意图,只会照代码去执行。这时,要跑出高性能,几乎全靠程序员写出低复杂度的代码。
延伸阅读: SPL 和 SQL 能不能融合在一起?

SPL 有多难学?

SPL 专门用于低代码和高性能。SPL 语法很容易,比 Java 简单多了,数小时即可掌握,数周就能熟练。难的是设计优化算法,好在这些能力都是可以学会的,我们已经把这些知识点总结成一系列“套路”,跟着学习就能掌握这些能力成为高手。
【程序设计】 前言及目录
【性能优化】 前言及目录
SPL 比 SQL 更难了还是更容易?


大多数程序员习惯了 SQL 思维方式,不熟悉高性能算法,需要用一两个场景训练和理解。性能优化套路并不是很多,几十招中常用的不超过十招,经历过也就学会了,算法设计和实现并不是那么难。最初的 2-3 个场景,需要由我方工程师介入配合用户实现,用户在这个过程中训练了思路、掌握了方法就能达到授人以渔的效果。

总结

最后我们来总结一下 esProc 用作数据分析引擎优势。

性能卓越
在实际应用中,esProc、的大数据处理性能可以比传统方案平均提升 1-2 个数量级,性能优势十分明显。

高效开发
借助 SPL 敏捷语法以及丰富的计算类库,在过程化的加持下采用自然思维就可以实现复杂算法,开发效率更高。

灵活开放
esProc 支持多数据源混合计算,有效利用多源优势的同时还能以最小代价实现 HTAP。而且 esProc 还可以集成嵌入到应用中使用,做到真正的开放、灵活。

节约资源
在高算力的支持下,esProc 使用更少硬件(单机顶集群)就能实现业务目标,因此更加环保,绿色低碳。

成本锐减
esProc 这些优势都反映到成本上就能达到开发、硬件、运维成本降低 X 倍的效果。