先说一下:因为还没找到更好的。.
先说原因。我们先来看看大数据平台都在做什么。
原因
结构化数据计算仍然是最重要的数据平台,主要满足海量数据存储和分析的需求。海量数据存储是真的。除了生产经营产生的结构化数据外,还有大量的音频、视频等非结构化数据,这些数据非常庞大,占用了大量的空间。有时候,超过80%的大数据平台存储的是非结构化数据。但是光存储数据是不够的,只有用起来才能产生价值,这就需要分析了。
大数据分析要分结构化数据和非结构化数据两部分来讨论。
结构化数据主要是企业生产经营过程中产生的业务数据,可以说是企业的核心。以前没有大数据平台的时候,企业主要或者完全使用这部分数据。随着业务的不断积累,这部分数据越来越大,传统的数据库方案面临着巨大的挑战。搭建大数据平台自然要解决这部分核心数据分析问题。
有了大数据平台,大家的想象力也放大了。过去无法使用的日志、图片、音视频等非结构化数据也会产生价值,这就涉及到对非结构化数据的分析。与核心业务数据分析相比,非结构化数据分析看起来更像是锦上添花。即便如此,非结构化数据分析并不是孤立存在的,但也会伴随着大量的结构化数据处理。在收集非结构化数据的同时,往往伴随着收集许多相关的结构化数据,如生产者、生产时间、类别、持续时间等;一些非结构化的数据经过处理也会转化为结构化的数据,比如访问者IP、访问时间、关键搜索词等。从网络日志中分解出来的。所谓的非结构化数据分析,实际上往往是针对这些伴生的结构化数据。
结构化数据分析仍然是大数据平台的重中之重。而且结构化数据处理技术也比较成熟,比如基于关系数据模型的关系数据库(SQL)。
SQL仍然是目前应用最广泛的结构化数据计算技术,但回归SQL是大数据计算语法的一个发展趋势。在Hadoop系统中,早期的猪拉丁已经被淘汰,但Hive一直很强;Spark SQL在Spark上用的也比较多,但是Scala用的少很多(Scala易学难掌握,不支持热部署作为编译语言有很多不便)。其他新的大数据计算系统通常使用SQL作为首选计算语法。经过几年的混战,SQL已经逐渐夺回了主动权。
这种现象大概有两个原因:
1. 实在没什么别的好用
数据库太普及,程序员对SQL相当熟悉,甚至思维习惯都是SQL式的。SQL做一些常规查询也相对简单。虽然不方便处理复杂的过程计算或有序操作,但其他替代技术也好不到哪里去。遇到SQL的高难度操作要写相当于UDF的复杂代码很麻烦,不如继续用SQL。
2. 大数据厂商的鼎力支持
大数据的技术本质是高性能,SQL是性能竞争的关键阵地。性能比面对同样的操作更有意义。过于专业化复杂的运营,涉及的影响因素太多,大数据平台本身的能力不好评估。SQL有TPC系列国际标准,所有用户都能理解,这样就有了明确的可比性,厂商也会把重点放在SQL的性能优化上。
兼容SQL更有利于大数据平台的移植。与SQL兼容的好处显而易见。SQL应用广泛,懂SQL的程序员也很多。如果继续采用SQL,可以避免很多学习成本。也有很多前端软件支持SQL,使用SQL的大数据平台很容易融入这个现成的生态系统。大数据平台打算替代的传统数据库也是SQL语法,所以兼容性会比较好,移植成本也会比较低。
好了,我们来说说为什么大数据平台会回归关系数据模型。那么继续使用关系数据模型(SQL)会有什么问题呢?
问题
性能低继续使用SQL最大的问题是很难获得大数据计算最需要的高性能。
SQL缺乏一些必要的数据类型和操作定义,使得一些高性能算法无法描述,只能寄希望于工程上的计算引擎优化。经过几十年的发展,传统的商业数据库在优化方面已经有了丰富的经验,但即便如此,仍然有很多场景难以得到优化,理论层面的问题确实很难在工程层面解决.然而,新兴的大数据平台在优化方面的经验却远不如传统数据库。如果算法不占优势,就只能依靠集群中更多的机器来提升性能。另外,SQL描述流程的能力不是很好,不擅长指定执行路径。但是为了获得高性能,往往需要对执行路径进行专门的优化,这就需要很多专门的修改器进行人为干预。还不如直接用过程语法更直接,这样也会阻碍用SQL写高性能代码。
SQL发明之初,计算机硬件能力还很差。要保证其实用性,SQL的设计必须适应当时的硬件条件,这使得SQL很难充分利用当代计算机的硬件能力,具体来说就是大内存、并行和集群。SQL中的JOIN对应的是键值,但是在内存比较大的情况下,其实可以直接对应地址,不需要计算哈希值和比较,性能可以提升很多。SQL的数据表是乱序的,在计算单个表的时候很容易实现并行分段。在计算多个表时,很难做到同步动态分段,所以很难根据机器的负载来临时确定并行数。集群操作也是如此。理论上,SQL不区分维度表和事实表。
JOIN 运算简单地定义为笛卡尔积后过滤,要实现大表 JOIN 就会不可避免地产生占用大量网络资源的 HASH Shuffle 动作,在集群节点数太多时,网络传输造成的延迟会超过节点多带来的好处。举个具体的例子,我们想在 1 亿条数据中取出前 10 名,用 SQL 写出来是这样的:
select top 10 x,y from T order by x desc这个语句中有个 order by,严格按它执行就会涉及大排序,而排序非常慢。其实我们可以想出一个不用大排序的算法,但用 SQL 却无法描述,只能指望数据库优化器了。对于这句 SQL 描述的简单情况,很多商用数据库确实都能优化,使用不必大排序的算法,性能通常很好。但情况复杂一些,比如在每个分组中取前 10 名,要用窗口函数和子查询把 SQL 写成这样:
select * from (select y,*,row_number() over (partition by y order by x desc) rn from T)where rn<=10这时候,数据库优化器就会犯晕了,猜不出这句 SQL 的目的,只能老老实实地执行排序的逻辑(这个语句中还是有 order by 的字样),结果性能陡降。
开发效率低不仅跑的慢,开发效率也不高,尤其在复杂计算方面,SQL 实现很繁琐。比如根据股票记录查询某只股票最长连续上涨天数,SQL(oracle)的写法如下:
SELECT MAX(ContinuousDays)-1 FROM ( SELECT code, NoRisingDays, COUNT(*) ContinuousDays FROM ( SELECT code, SUM(RisingFlag) OVER (PARTITION BY code ORDER BY day) NoRisingDays FROM ( SELECT code, day, CASE WHEN price> LAG(price) OVER (PARTITION BY code ORDER BY day) THEN 0 ELSE 1 END RisingFlag FROM stock ) ) GROUP BY NoRisingDays )用了很绕的方式实现,别说写出来,看懂都要半天。
此外,SQL 也很难实现过程计算。什么是过程性计算呢?就是一步写不出来,需要多次分步运算,特别是与数据次序相关的运算。
我们举几个例子来看:
一周内累计登录时长超过一小时的用户占比,但要除去登录时长小于 10 秒的误操作情况
信用卡在最近三个月内最长连续消费的天数分布情况,考虑实施连续消费 10 天后积分三倍的促销活动
一个月中有多少用户在 24 小时连续操作了查看商品后加入购物车并购买的的动作,有多少用户在中间步骤中放弃?
……
(为了便于理解,这些例子已经做了简化,实际情况的运算还要复杂很多)
这类过程性运算,用 SQL 写出来的难度就很大,经常还要写 UDF 才能完成。如果 SQL 写都写不出来,那么 SQL 的使用效果将大打折扣。
开发效率低导致性能低复杂 SQL 的执行效率往往也很低,这就又回到性能的问题了,实际上开发效率和计算性能是密切相关的,很多性能问题本质上是开发效率造成。
复杂 SQL 的优化效果很差,在嵌套几层之后,数据库引擎也会晕掉,不知道如何优化。提高这类复杂运算的性能,指望计算平台的自动优化就靠不住了,根本手段还要靠写出高性能的算法。象过程式运算中还常常需要保存中间结果以复用,SQL 需要用临时表,多了 IO 操作就会影响性能,这都不是引擎优化能解决的事情,必须要去改写计算过程。
所以,本质上,提高性能还是降低开发难度。软件无法提高硬件的性能,只能想办法设计复杂度更低的算法,而如果能够快速低成本地实现这些算法,那就可以达到提高性能的目标。如果语法体系难以甚至没办法描述高性能算法,必须迫使程序员采用复杂度较高的算法,那也就很难再提高性能了。优化 SQL 运算无助于降低它的开发难度,SQL 语法体系就是那样,无论怎样优化它的性能,开发难度并不会改变,很多高性能算法仍然实现不了,也就难以实质性地提高运算性能。
编写 UDF 在许多场景时确实能提高性能,但一方面开发难度很大,另一方面这是程序员硬写的,也不能利用到 SQL 引擎的优化能力。而且经常并不能将完整运算都写成 UDF,只能使用计算平台提供的接口,仍然要在 SQL 框架使用它的数据类型,这样还是会限制高性能算法的实现。
根本的解决方法,还是要让大数据平台真地有一些更好用的语法。
解法
使用开源集算器 SPL 就可以作为 SQL 很好的替代和延伸,作为大数据平台专用的计算语言,延续 SQL 优点的同时改善其缺点。
SPL 是一款专业的开源数据计算引擎,提供了独立的计算语法,整个体系不依赖关系数据模型,因此在很多方面都有长足突破,尤其在开发效率和计算性能方面。下面来盘点一下 SPL 都有哪些特性适用于当代大数据平台。
强集成性首先是集成性,不管 SPL 多优秀,如果与大数据平台无法结合使用也是白费。要在大数据平台中使用 SPL 其实很方便,引入 jar 包就可以使用(本身也是开源的,想怎么用就怎么用)。SPL 提供了标准 JDBC 驱动,可以直接执行 SPL 脚本,也可以调用 SPL 脚本文件。
…Class.forName("com.esproc.jdbc.InternalDriver");Connection conn =DriverManager.getConnection("jdbc:esproc:local://");Statement st = connection.();//直接执行SPL脚本//ResultSet rs = st.executeQuery("=100.new(~:baseNum,~*~:square2)");//调用SPL脚本文件CallableStatement st = conn.prepareCall("{call SplScript(?, ?)}");st.setObject(1, 3000);st.setObject(2, 5000);ResultSet result=st.execute();...高效开发敏捷语法在结构化数据计算方面,SPL 提供了独立的计算语法和丰富的计算类库,同时支持过程计算使得复杂计算实现也很简单。前面举的计算股票最长连涨天数的例子,用 SPL 实现是这样的:
A
1
=db.query("select * from stock order by day")
2
=A1.group@i(price<price<-1>).max(~.len())-1
按交易日排好序,将连涨的记录分到一组,然后求最大值 -1 就是最长连续上涨天数了,完全按照自然思维实现,不用绕来绕去,比 SQL 简单不少。
再比如根据用户登录记录列出每个用户最近一次登录间隔:
A
1
=ulogin.groups(uid;top(2,-logtime))
最后2个登录记录
2
=A1.new(uid,#2(1).logtime-#2(2).logtime:interval)
计算间隔
支持分步的 SPL 语法完成过程计算很方便。
SPL 提供了丰富的计算类库,可以更进一步简化运算。
直观易用开发环境同时,SPL 还提供了简洁易用的开发环境,单步执行、设置断点,所见即所得的结果预览窗口…,开发效率也更高。
多数据源支持SPL 还提供了多样性数据源支持,多种数据源可以直接使用,相比大数据平台需要数据先“入库”才能计算,SPL 的体系更加开放。
SPL 支持的部分数据源(仍在扩展中…)
不仅如此,SPL 还支持多种数据源混合计算,充分发挥各类数据源自身的优势,扩展大数据平台的开放性。同时,直接使用多种数据源开发实现上也更简单,进一步提升开发效率。
热切换SPL 是解释执行的,天然支持热切换,这对 Java 体系下的大数据平台是重大利好。基于 SPL 的大数据计算逻辑编写、修改和运维都不需要重启,实时生效,开发运维更加便捷。
高计算性能前面我们说过,高性能与高开发效率本质上是一回事,基于 SPL 的简洁语法更容易写出高性能算法。同时,SPL 还提供了众多高性能数据存储和高性能算法机制,SQL 中很难实现的高性能算法及存储方案用 SPL 却可以轻松实现,而软件提高性能关键就在于算法和存储。
例如前面说过的 TopN 运算,在 SPL 中 TopN 被理解为聚合运算,这样可以将高复杂度的排序转换成低复杂度的聚合运算,而且很还能扩展应用范围。
A
1
=file(“data.ctx”).create().cursor()
2
=A1.groups(;top(10,amount))
金额在前 10 名的订单
3
=A1.groups(area;top(10,amount))
每个地区金额在前 10 名的订单
这里的语句中没有排序字样,也不会产生大排序的动作,在全集还是分组中计算 TopN 的语法基本一致,而且都会有较高的性能。