背景
大数据仓库 Hive,作为一个成功的大数据仓库,它将 SQL 语句转换成 MapReduce 执行过程,并把大数据应用的门槛下降到普通数据分析师和工程师就可以很快上手的地步。
但是 Hive 也有自己的问题,由于它使用自己定义的 Hive QL 语法,这对已经熟悉 Oracle 等传统数据仓库的分析师来说,还是有一定的上手难度。特别是很多企业使用传统数据仓库进行数据分析已经由来已久,沉淀了大量的 SQL 语句,并且这些 SQL 经过多年的修改打磨,非常庞大也非常复杂。这样的 SQL 光是完全理解可能就要花很长时间,再转化成 Hive QL 就更加费力,还不说转化修改过程中可能引入的 bug。
要想那些在 Oracle 上运行良好的 SQL 可以直接运行在 Hadoop 上,而不需要重写成 Hive QL,必须要自己开发一款能够支持标准数据库 SQL 的大数据仓库引擎,就比如李智慧老师曾经参与的Panthera项目。
Hive QL 的主要处理过程
- 将输入的 Hive QL 经过语法解析器转换成 Hive 抽象语法树(Hive AST)。
- 将 Hive AST 经过语义分析器转换成 MapReduce 执行计划。
- 将生成的 MapReduce 执行计划和 Hive 执行函数代码提交到 Hadoop 上执行。
再看Panthera设计
Panthera 的设计思路是保留 Hive 语义分析器不动,替换 Hive 语法解析器,使其将标准 SQL 语句转换成 Hive 语义分析器能够处理的 Hive 抽象语法树。用图形来表示的话,是用红框内的部分代替黑框内原来 Hive 的部分。
红框内的组件我们重新开发过,浅蓝色的是我们使用的一个开源的 SQL 语法解析器,将标准 SQL 解析成标准 SQL 抽象语法树(SQL AST),后面深蓝色的就是团队自己开发的 SQL 抽象语法树分析与转换器,将 SQL AST 转换成 Hive AST。
标准 SQL 和 Hive QL 的差别在哪里
差别1:语法表达方式
Hive QL 语法和标准 SQL 语法略有不同;
差别2: 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的AST(抽象语法树),程序通过使用装饰模式的设计来不断扩展支持更多语法,再使用组合模式对抽象语法树进行遍历,从而等价转换成Hive格式的AST,就可以交给 Hive 的语义分析器去处理了,从而也就实现了对标准 SQL 的支持。
思考题
SQL 注入是一种常见的 Web 攻击手段,如下图所示,攻击者在 HTTP 请求中注入恶意 SQL 命令(drop table users;),服务器用请求参数构造数据库 SQL 命令时,恶意 SQL 被一起构造,并在数据库中执行。
但是 JDBC 的 PrepareStatement 可以阻止 SQL 注入攻击,MyBatis 之类的 ORM 框架也可以阻止 SQL 注入,请从数据库引擎的工作机制解释 PrepareStatement 和 MyBatis 的防注入攻击的原理。
来自极客时间的精选留言
大神1
因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or '1=1’也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令,如此,就起到了SQL注入的作用了
大神2
基于SQL的大数据仓库引擎panthera的核心任务是把SQL语义与Hive AST对应起来。难点是SQL的语义远比Hive AST丰富,而幸运的事SQL丰富的表意逻辑主要源于它的嵌套子语句,这在Hive AST中是不存在的。但是SQL的嵌套子语句可以等价于若干jion操作。
为了在工程上降低实现难度,特意为每个语法点设计一个对象(类),这就将复杂问题分解为无数个小步骤,可以持续交付,不用长期等待,从而将不可能有条件的变为可能。而且每个类的代码十分简洁,遇到问题也便于各个击破。
该笔记摘录自极客时间课程
《从0开始学大数据》