如今,很多公司可能会在内部使用多种数据存储和处理系统。这些不同的系统解决了对应的使用案例。除了传统的RDBMS (比如Oracle DB,Teradata或PostgreSQL) 之外,我们还会使用Apache Kafka来获取流和事件数据。使用Apache Druid处理实时系列数据(real-time series data),使用Apache Phoenix进行快速索引查找。 此外,我们还可能使用云存储服务或 HDFS 批量存储数据。
平台团队一般会部署所有这些系统,使应用程序开发人员可以灵活地选择,以满足他们业务分析需求所需的功能。
使用Apache Hive 3.0和SQL统一访问
但是我们也知道,如果我们需要将不同存储来源的数据进行关联,我们需要对数据进行提取,并放到同一种存储介质里面,比如都放到HBase 中,然后再进行关联操作。大家可以看出,这种数据割裂,会对我们的数据关联分析带来很大的麻烦,如果我们能够使用一种查询引擎分别查询不同数据源的数据,然后直接进行关联操作,这将带来巨大的效率提升。这就是本文介绍的JDBC Storage Handler,详见HIVE-1555。
从JdbcStorageHandler名字我们就可以看出,其功能应该和HBaseStorageHandler 类似,也就是可以在Hive中使用标准的JDBC方式读取存储在不同数据存储里面的数据。比如我们可以在 Hive 中分别读取MySQL和Phoenix里面的数据,然后进行关联。其提供高效,统一的SQ 访问- 开箱即用。 这样做的好处是巨大的:
单个SQL方言和API
统一安全控制和审计跟踪
统一控制
能够组合来自多个来源的数据
数据独立性
需要注意的是,目前JdbcStorageHandler 仅仅支持从JDBC数据源读取数据,还不支持支持将数据写入到JDBC数据源。
JdbcStorageHandler支持CBO
使用JdbcStorageHandler从JDBC数据源读取数据时,一种简单的方式是直接读取全量的数据;并将其全部加载到Hive。这种方式虽然很简答,但是却会带来性能问题。
基于这些原因,Hive依赖storage handler interfaces以及Apache Calcite的CBO实现了智能的算子下推功能。这样可以将查询规则下推到 JDBC 数据源,在 JDBC 数据源层面上进行一些过滤,再将计算结果返回给Hive,这样可以减少数据的量,从而提高查询效率。
算子下推这个功能不限于SQL系统,比如我们可以将算子下推到Apache Druid或者Apache Kafka。在查询Apache Druid里面的数据时,Hive可以将过滤和聚合操作下推到Druid,生成JSON查询,并将其发送到引擎公开的REST API。另一方面,如果我们查询Kafka里面的数据时,Hive可以直接过滤相关的分区或者偏移量,有选择地从系统中的主题读取数据。
假设我们在MySQL或者PostgreSQL里面有store_sales、store_retuens和date_dim三张表,然后我们有以下的查询:
上面这条SQL在优化前的执行计划,如下:
其中灰色的框框是在MySQL或者PostgreSQL里面执行的,橘色的是在Hive 执行的。从上图可以看出,三次扫描的文件直接返回到Hive处理,这样效率是很低下的,其实我们可以对其进行算子下沉优化,经过Apache Calcite的CBO优化之后,执行计划如下:
对应的SQL执行如下:
上面的这些操作直接在对应的JDBC数据源上执行,然后Hive再调用JDBC_Scan将查询结果保存到对应的Sink中。
如何使用JdbcStorageHandler
说了这么多,那么我们该如何使用JdbcStorageHandler 呢?为了使用它,我们需要在Hive里面创建一张外部表,具体如下: