开发一个不需要重写成Hive QL的大数据SQL引擎

本文探讨开发一个能够直接运行标准SQL于Hadoop上的大数据仓库引擎,避免将Oracle SQL转换为Hive QL的过程。文章介绍了将标准SQL转换为Hive可处理的语法树的思路,以及解决复杂嵌套子查询的转换方法,同时讨论了SQL注入及其防护机制。
摘要由CSDN通过智能技术生成

🚀 优质资源分享 🚀

学习路线指引(点击解锁)知识定位人群定位
🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

**摘要:**开发一款能支持标准数据库SQL的大数据仓库引擎,让那些在Oracle上运行良好的SQL可以直接运行在Hadoop上,而不需要重写成Hive QL。

本文分享自华为云社区《​​​​​​​​​​​​​​从零开发大数据SQL引擎》,作者:JavaEdge 。

学习大数据技术的核心原理,掌握一些高效的思考和思维方式,构建自己的技术知识体系。明白了原理,有时甚至不需要学习,顺着原理就可以推导出各种实现细节。

各种知识表象看杂乱无章,若只是学习繁杂知识点,固然自己的知识面是有限的,并且遇到问题的应变能力也很难提高。所以有些高手看起来似乎无所不知,不论谈论起什么技术,都能头头是道,其实并不是他们学习、掌握了所有技术,而是他们是在谈到这个问题时,才开始进行推导,并迅速得出结论。

高手不一定要很资深、经验丰富,把握住技术的核心本质,掌握快速分析推导的能力,能迅速将自己的知识技能推到陌生领域,就是高手。

本系列专注大数据开发需要关注的问题及解决方案。跳出繁杂知识表象,掌握核心原理和思维方式,进而融会贯通各种技术,再通过各种实践训练,成为终极高手。

大数据仓库Hive

作为一个成功的大数据仓库,它将SQL语句转换成MapReduce执行过程,并把大数据应用的门槛下降到普通数据分析师和工程师就可以很快上手的地步。

但Hive也有问题,由于它使用自定义Hive QL,对熟悉Oracle等传统数据仓库的分析师有上手难度。特别是很多企业使用传统数据仓库进行数据分析已久,沉淀大量SQL语句,非常庞大也非常复杂。某银行的一条统计报表SQL足足两张A4纸,光是完全理解可能就要花很长时间,再转化成Hive QL更费力,还不说可能引入bug。

开发一款能支持标准数据库SQL的大数据仓库引擎,让那些在Oracle上运行良好的SQL可以直接运行在Hadoop上,而不需要重写成Hive QL。

Hive处理过程

  1. 将输入的Hive QL经过语法解析器转换成Hive抽象语法树(Hive AST)
  2. 将Hive AST经过语义分析器转换成MapReduce执行计划
  3. 将生成的MapReduce执行计划和Hive执行函数代码提交到Hadoop执行

可见,最简单的,对第一步改造即可。考虑替换Hive语法解析器:能将标准SQL转换成Hive语义分析器能处理的Hive抽象语法树,即红框代替黑框。


红框内:浅蓝色是个开源的SQL语法解析器,将标准SQL解析成标准SQL抽象语法树(SQL AST),后面深蓝色定制开发的SQL抽象语法树分析与转换器,将SQL AST转换成Hive AST。

那么关键问题就来了:

标准SQL V.S Hive QL

  • 语法表达方式,Hive QL语法和标准SQL语法略有不同
  • Hive QL支持的语法元素比标准SQL要少很多,比如,数据仓库领域主要的测试集TPC-H所有的SQL语句,Hive都不支持。尤其是Hive不支持复杂嵌套子查询,而数据仓库分析中嵌套子查询几乎无处不在。如下SQL,where条件existes里包含了另一条SQL:
select o\_orderpriority, count(*) as order\_count
from orders
where o\_orderdate >= date '[DATE]'
 and o\_orderdate < date '[DATE]' + interval '3' month
 and exists
 (select *
     from lineitem
 where l\_orderkey = o\_orderkey
 and l\_commitdate < l\_receiptdate)
group by o\_orderpriority
order by o\_orderpriority;

开发支持标准SQL语法的SQL引擎难点,就是消除复杂嵌套子查询掉,即让where里不包含select。

SQL理论基础是关系代数,主要操作仅包括:并、差、积、选择、投影。而一个嵌套子查询可等价转换成一个连接(join)操作,如:

select s\_grade
from staff
where s\_city not in (
 select p\_city
 from proj
 where s\_empname = p\_pname
)

这是个在where条件里嵌套了not in子查询的SQL语句,它可以用left outer join和left semi join进行等价转换,示例如下,这是Panthera自动转换完成得到的等价SQL。这条SQL语句不再包含嵌套子查询,

select panthera\_10.panthera\_1 as s\_grade from (select panthera\_1, panthera\_4, panthera\_6, s\_empname, s\_city from (select s\_grade as panthera\_1, s\_city as panthera\_4, s\_empname as panthera\_6, s\_empname as s\_empname, s\_city as s\_city from staff) panthera\_14 left outer join (select panthera\_16.panthera\_7 as panthera\_7, panthera\_16.panthera\_8 as panthera\_8, panthera\_16.panthera\_9 as panthera\_9, panthera\_16.panthera\_12 as panthera\_12, panthera\_16.panthera\_13 as panthera\_13 from (select panthera\_0.panthera\_1 as panthera\_7, panthera\_0.panthera\_4 as panthera\_8, panthera\_0.panthera\_6 as panthera\_9, panthera\_0.s\_empname as panthera\_12, panthera\_0.s\_city as panthera\_13 from (select s\_grade as panthera\_1, s\_city as panthera\_4, s\_empname as panthera\_6, s\_empname, s\_city from staff) panthera\_0 left semi join (select p\_city as panthera\_3, p\_pname as panthera\_5 from proj) panthera\_2 on (panthera\_0.panthera\_4 = panthera\_2.panthera\_3) and (panthera\_0.panthera\_6 = panthera\_2.panthera\_5) where true) panthera\_16 group by panthera\_16.panthera\_7, panthera\_16.panthera\_8, panthera\_16.panthera\_9, panthera\_16.panthera\_12, panthera\_16.panthera\_13) panthera\_15 on ((((panthera\_14.panthera\_1 <=> panthera\_15.panthera\_7) and (panthera\_14.panthera\_4 <=> panthera\_15.panthera\_8)) and (panthera\_14.panthera\_6 <=> panthera\_15.panthera\_9)) and (panthera\_14.s\_empname <=> panthera\_15.panthera\_12)) and (panthera\_14.s\_city <=> panthera\_15.panthera\_13) where ((((panthera\_15.panthera\_7 is null) and (panthera\_15.panthera\_8 is null)) and (panthera\_15.panthera\_9 is null)) and (panthera\_15.panthera\_12 is null)) and (panthera\_15.panthera\_13 is null)) panthera\_10 ;
通过可视化工具将上面两条SQL的语法树展示出来,是这样的。


这是原始的SQL抽象语法树。


这是等价转换后的抽象语法树,内容太多被压缩的无法看清,不过你可以感受一下(笑)。

那么,在程序设计上如何实现这样复杂的语法转换呢?当时Panthera项目组合使用了几种经典的设计模式,每个语法点被封装到一个类里去处理,每个类通常不过几十行代码,这样整个程序非常简单、清爽。如果在测试过程中遇到不支持的语法点,只需为这个语法点新增加一个类即可,团队协作与代码维护非常容易。

使用装饰模式的语法等价转换类的构造,Panthera每增加一种新的语法转换能力,只需要开发一个新的Transformer类,然后添加到下面的构造函数代码里即可。

 private static SqlASTTransformer tf =
      new RedundantSelectGroupItemTransformer(
 new DistinctTransformer(
 new GroupElementNormalizeTransformer(
 new PrepareQueryInfoTransformer(
 new OrderByTransformer(
 new OrderByFunctionTransformer(
 new MinusIntersectTransformer(
 new PrepareQueryInfoTransformer(
 new UnionTransformer(
 new Leftsemi2LeftJoinTransformer(
 new CountAsteriskPositionTransformer(
 new FilterInwardTransformer(
 //use leftJoin method to handle not exists for correlated
      new CrossJoinTransformer(
 new PrepareQueryInfoTransformer(
 new SubQUnnestTransformer(
 new PrepareFilterBlockTransformer(
 new PrepareQueryInfoTransformer(
 new TopLevelUnionTransformer(
 new FilterBlockAdjustTransformer(
 new PrepareFilterBlockTransformer(
 new ExpandAsteriskTransformer(
 new PrepareQueryInfoTransformer(
 new CrossJoinTransformer(
 new PrepareQueryInfoTransformer(
 new ConditionStructTransformer(
 new MultipleTableSelectTransformer(
 new WhereConditionOptimizationTransformer(
 new PrepareQueryInfoTransformer(
 new InTransformer(
 new TopLevelUnionTransformer(
 new MinusIntersectTransformer(
 new NaturalJoinTransformer(
 new OrderByNotInSelectListTransformer(
 new RowNumTransformer(
 new BetweenTransformer(
 new UsingTransformer(
 new SchemaDotTableTransformer(
 new NothingTransformer())))))))))))))))))))))))))))))))))))));

而在具体的Transformer类中,则使用组合模式对抽象语法树AST进行遍历,以下为Between语法节点的遍历。我们看到使用组合模式进行树的遍历不需要用递归算法,因为递归的特性已经隐藏在树的结构里面了。

 @Override
 protected void transform(CommonTree tree, TranslateContext context) throws SqlXlateException {
 tf.transformAST(tree, context);
 trans(tree, context);
 }

 void trans(CommonTree tree, TranslateContext context) {
 // deep firstly
    for (int i = 0; i < tree.getChildCount(); i++) {
 trans((CommonTree) (tree.getChild(i)), context);
 }
 if (tree.getType() == PantheraExpParser.SQL92\_RESERVED\_BETWEEN) {
 transBetween(false, tree, context);
 }
 if (tree.getType() == PantheraExpParser.NOT\_BETWEEN) {
 transBetween(true, tree, context);
 }
 }

将等价转换后的抽象语法树AST再进一步转换成Hive格式的抽象语法树,就可以交给Hive的语义分析器去处理了,从而也就实现了对标准SQL的支持。

当时Facebook为证明Hive对数据仓库的支持,手工将TPC-H的测试SQL转换成Hive QL,将这些手工Hive QL和Panthera进行对比测试,两者性能各有所长,总体上不相上下,说明Panthera自动进行语法分析和转换的效率还行。

Panthera(ASE)和Facebook手工Hive QL对比测试:


标准SQL语法集的语法点很多,007进行各种关系代数等价变形,也不可能适配所有标准SQL语法。

SQL注入

常见的Web攻击手段,如下图所示,攻击者在HTTP请求中注入恶意SQL命令(drop table users;),服务器用请求参数构造数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。


但JDBC的PrepareStatement可阻止SQL注入攻击,MyBatis之类的ORM框架也可以阻止SQL注入,请从数据库引擎的工作机制解释PrepareStatement和MyBatis的防注入攻击的原理。

点击关注,第一时间了解华为云新鲜技术~

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组一个器和一个判别器,它们相互竞争,生器生数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值