hive3.x特性

转自:https://www.infoq.cn/profile/44F5923A45102D/publish

hive架构演进

按照 METASTORE SERVICE/DB 所处的位置,经常会提到三种模式:内嵌模式,本地模式,远程模式:

  • 内嵌模式:客户端和服务端还有底层存储元数据的数据库是同一个进程(即不区分客户端和服务端)。

  • 本地模式:在内嵌模式的基础上,把存储元数据的数据库拆分了出来,但客户端和服务端还是同一个进程,是一体的(即不区分客户端和服务端)。

  • 远程模式:在本地模式的基础上,把元数据服务 hms 也拆分出来作为一个单独的进程,有了真正意义上的客户端和服务端,从 HIVE1.X 开始,所有生产环境推荐使用的都是 remote metastore 模式。

远程模式

  1. 在服务端,包括一个或多个查询引擎 HiveServer2 和一个元数据引擎 HMS (Hive Metastore Service);

  2. 从客户端使用方式来看,在 hive1.x 和 hive2.x 中又可以进一步分为两种方式:hive cli 的胖客户端模式,和 beeline 的瘦客户端模式;

  3. Hive cli 的胖客户端模式,客户端承载了 hiveserver2 的查询引擎角色,只需要访问服务端的元数据服务 hms 即可;

  4. Beeline 的瘦客户端模式,hiveserver2运行在服务端,客户端需要访问服务端的 hiveserver2 ,并通过 hiveserver2 访问底层的 hms;

  5. 从 hive3.x 开始,hive 不再支持 cli 胖客户端模式, 仅仅支持 beeline 瘦客户端模式;

发展新特性

  • HIVE 将客户端与服务端分离,并在服务端进一步按照功能拆分出 hiveserver2 和 hms 两个服务,就可以应对多个客户端的并发访问,也能够适配大数据生态的其它计算引擎,如 spark/impala/presto/flink;

  • 为了提高数据质量,也为了提高数据查询和分析的效率 Hive 社区还孵化出了列式存储 orc ,目前 Orc 已经是 apache 顶级项目;

  • HIVE 进一步补强优化了 hiveserver2 服务端,通过 ORC 事务表提供了对增删改查的完善的 ACID 语义的支持,也通过 LLAP 加强了互动查询的效率,还通过 streaming 增强了实时流处理能力;

  • 综上所述, HIVE 已经从早期一个简单的存储引擎之上的 SQL 解析层(单纯的 JAR 而没有服务),逐渐迭代优化,补齐功能短板,越来越像传统的关系型数据库,成为一个完善的数据仓库解决方案了!

  • 注意 1: HIVE 是针对数据仓库的 OLAP 场景,不是针对事务交易的 OLTP 场景,不能当做 OLTP 数据库来 使 用!

  • 注意 2:虽然 HIVE 做了大量性能方面的优化,但由于它是存算分离的架构,在执行时也需要向 YARN 等资源管理器动态申请资源,所以其查询性能一般比 OLAP 数据库还是要差些的,比如 GP/DORIS/CK 等。

HIVE3.X 和 HIVE2.X 的那些重大差异

HIVE3.X 不再支持以下特性:

  • Hive cli: HIVE3.X 不再支持 胖客户端 Hive CLI, 仅支持瘦客户端 beeline;

  • Hive on mr: HIVE3.X 底层执行引擎不再支持 hive on mr , CDP 中也不再支持 hive on spark 仅支持 hiveon tez (Hive on Tez 提供更好的 ETL 性能);

  • Hive index: 通过 HIVE 18448 在 hive 3.x 中彻底移除了对 Index 的支持;(orc/parquet 列式文件存储格式本身提供了对 index 和 bloom filter 的支持, 相关参数 hive.optimize.index.filter 默认为 true; hive2.3.0 也增加了对物化视图 materialzed views 的 automatic rewriting 的支持,这些功能很好地替代了 Index);

在 DDL 执行效果上,HIVE3.X 和 HIVE2.X 有以下差异:

  • HIVE3.X CREATE TABLE,不指定格式时,默认 为 ORC 格式,之前版本默认为 text 格式;

  • HIVE3.X CREATE TABLE,不指定是否为事务表时,默认为 ORC 事务内表,之前版本默认为 ORC 非事务内表;

  • Hive3.x 的 ORC 事务内表,支持高效 的 insert/update/delete/merge, 且不再需要进行分桶;

  • Hive3.x 的 ORC 事务内 表,分为 full acid 事务内表,和 Insert only 事务内表: TBLPROPERTIES(‘transactional’=‘true',transactional_properties='insert_only’或'default');

  • HIVE3.X 增加了新的语法 CREATE MANAGED TABLE xyz(col1 type,...) type,...),来显示创建 managed table;

  • HIVE3.X 中,external 外表有两种类型:external purge table 和 external non purge table: TBLPROPERTIES ('EXTERNAL'='TRUE',external.table.purge’=’TRUE;

  • Hive3.x 中,内表和外表的默认存储路径,分别由参数 hive.metastore.warehouse.dir 和 hive.metastore.warehouse.external.dir 控制,在 cdp 中默认值分别为 /warehouse/ tablespace/managed/hive 和 /warehouse/ tablespace/external/hive;

  • HIVE3.X 中,内表和外表的存储路径,分别可以在 DATABASE” 级别和 “TABLE” 级别通过 location 参数来修改;

  • HIVE3.X CREATE TABLE 创建 managed table 时,推荐不在 TABLE 级别指定 location ,此时会使用 hive.metastore.warehouse.dir 指定的默认值或 DATABASE 级别覆盖的值;(如果指定路径,路劲的值必须是 managedwarehouse root dir 或 database 的 managedLocationUrI 之下的路径);

  • HIVE3.X CREATE TABLE 创建 external table 时, 也推荐不指定 location,此时会使用参数 hive.metastore.warehouse.external.dir 指定的默认值 (也可以在 TABLE 级别来指定);

  • HIVE3.X Drop external table 时,会不会删除表底层实际的数据,取决于参数 external.table.purge;

  • HIVE3.X truncate table,只能对内部 表,或‘external.table.purge’=’TRUE' 的外部表,才能被 truncate ;(否则会报错);

HIVE3.X 相比 HIVE2.X,重大参数变化如下:

  • hive.default.fileformat.managed:升级前 None,升级后 ORC;

  • hive.metastore.disallow.incompatible.col.type.changes:控制是否允许更改不兼容的列类型,比如将 STRING 列更改为 INT 列;升级前 FALSE,升级后 TRUE;

  • hive.metastore.warehouse.dir:升级前 /user/hive/warehouse,升级后/tablespace /managed/hive;

  • hive.server2.enable.doAs:升级前 TRUE (in case of unsecure cluster only),升级后 FALSE;

  • hive.txn.manager:升级前 org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager ,升级后 org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;

  • hive.execution.engine:升级前 mr,升级后 tez;

  • hive.cbo.enable: 升级前 FALSE,升级后 TRUE;

  • hive.auto.convert.sortmerge.join/hive.auto.convert.sortmerge.join.reduce.side: 升级前: FALSE in the old CDH,TRUE in the old HDP; 升级后 TRUE;

  • hive.auto.convert.sortmerge.join.to.mapjoin: 升级前 FALSE,升级后 TRUE;

  • hive.exec.dynamic.partition.mode:升级前 strict,升级后 nonstrict;

  • hive.exec.max.dynamic.partitions:升级前 1000,升级后 5000;

  • hive.exec.max.dynamic.partitions.pernode:升级前 100,升级后 2000;

HIVE3.X 的 ORC 事务表

HIVE 的一个最主要的发展趋势,就是已经从早期一个简单的存储引擎之上的 SQL 解析层(单纯的 JAR 而没有服务),逐渐迭代优化,补齐功能短板,越来越像传统的关系型数据库,成为一个完善的数据仓库解决方案了!这其中最显眼的功能点,就是 HIVE 推出的 ORC ACID 事务表,通过该特性,HIVE 可以向其它流行的数据湖框架 deltaLake/hudi/iceberg 一样,通过 ACID 事务特性,提供对并发读写的支持,提供记录级别的增删改查。

  • 在默认情况 下 HIVE3.X CREATE TABLE 语句会在 Hive Metastore 中创建一个 ORC 格式的 Full ACID v2 事务内表;

  • Hive 严格控制对 ORC 事务表的访问,并定期在后台对表执行压缩 compaction 操作 当然, Spark 和其他客户端访问 Hive ORC 事务表的方式也相应地需要作出变化);

  • 与 Non ACID 表相比, Hive Full ACID v2 (事务内表)提供了更好的批量性能、安全保障和用户体验

  • Full ACID v2 Hive 表有以下四个特点:支持 Insert/Update/Delete/Merge 操作;ETL 性能与 Non ACID 表一样好;无需进行分桶操作;与 S3 等云端对象存储完全兼容;

  • 与 Non ACID 表相比, Hive Full ACID v2(事务内表 )提供了 row 级别的 ACID 语义,而不再仅仅是 table 或 partition 级别的 ACID ,并基于此支持了以下场景:提供了多任务并发读写同一个表或同一个分区的能力: one application can add rows while another reads from the same partition without interfering with each other;提供了对 Streaming ingest of data 的支持:不再引起 dirty read 和 小 文件问题;(可以更好地对接 flink/kafka/flume)提供了对数仓的 SCD Slowly changing dimensions 的支持:HIVE ACID 通过提供记录级别的 inserts/delete,可以完善地支持数仓星型模型的缓慢渐变维度;提供了记录级别的数据修复 data restatement 功能:HIVE ACID 通过提供记录级别的 Insert/Update/Delete,支持了数据修复和删除功能;提供了批量更新功能:通过 Merge 提供了批量更新功能;

事务表主要参数如下:

1.ORC 事务表客户端相关参数:hive.support.concurrency:true(是否使用事务管理器,默认true)

hive.enforce.bucketing: true (是否强制分桶,默认true)

不在需要的 Hive 2.0参数: hive.exec.dynamic.partition.mode: nonstrict(动态分区)

hive.txn.manager:org.apache.hadoop.hive.ql.lockmgr.DbTxnManager(锁实现)

2.ORC 事务表服务端相关参数(hms):hive.compactor.initiator.on:true(自动合并小文件)

hive.compactor.worker.threads: a positive number on at least one instance of the Thrift metastore service

HIVE3 对事务表新增了一些命令,主要有以下这些:

  • 提供了对以下 DML 命令的支持: INSERT…VALUES, UPDATE,DELETE,merge into;

  • 可以通过以下命令查看压缩任务,事务,锁等:SHOW TRANSACTIONS/COMPACTIONS/LOCKS;

  • 可以通过以下命令手动触发对表的压缩:Alter table xxx compact ‘minor/ major’and wait (自动压缩之外的补充)

  • MERGE INTO 是一个很方便的命令,其语法如下:

HIVE3.X 的 LEGACY 传统模式

  1. Cloudera 推出 了 Hive 的 LEGACY 传统 模式,并回馈给了 APACHE HIVE 开源社区,以缓解 HIVE/CDP 在升级/迁移期间的脚本兼容性问题。

  2. HIVE3.X 的 legacy 传统模式,可以通过参数 hive.create.as.external.legacy 来开启,需要说明的是,该参数在推出之初,社区就明确指出,“This config is temporary and will be deprecated later”,所以长远来看,还是推荐大家学习 HIVE3.X 的这些新特性,并逐渐摒弃对传统模式的以来;

  3. 执行命令 SET hive.create.as.external.legacy 查看是否支持该参数,如果显示 xx is undefined ,则表示不支持 LEGACY 模式。

  4. 在 HIVE3.X 中,根据 DROP TABLE 时是否删除底层存储系统 HDFS 中的数据,external 外表又被分为两种类型:external non purgeable table 和 external purge table,前者在 DROP TABLE 时跟 HIVE2.X 的外表行为一致,不会删除底层 HDFS 中的数据;而后者 DROP TABLE 时跟 HIVE2.X 的内表行为一致,也会删除底层 HDFS 中的数据;

  5. HIVE3.X 中创建外表时外表的具体类型,可以通过 session 级别参数 hive.external.table.purge.default 控制,也可以在建表时在 table 级别进行覆盖:TBLPROPERTIES (‘EXTERNAL’=‘TRUE’,‘external.table.purge’=’TRUE'/'FALSE');

  6. Hive3.x 的 ORC 事务内表,也分为两种类型,即 full acid 事务内表,和 Insert only 事务内表,可以通过 session 级别参数 hive.create.as.acid hive.create.as.insert.only 控制,也可以在创建表时在 table 级别覆盖:TBLPROPERTIES (‘transactional’=‘true','transactional_properties='insert_only ’/‘default');

  7. Hive3.x CREATE TABLE 默认创建的是 Managed ORC ACID table, 而 Hive1 和 hive2 默认创建的是 Managed (Non ACID ) txtfile table;

  8. HIVE3.X CREATE TABLE 的实际效果,取决于以下参数:hive.create.as.external.legacy/hive.create.as.acid/hive.create.as.insert.only/hive.txn.manager hive.ctas.external.tables/hive.external.table.purge.default/hive.default.fileformat.managed/hive.metastore.warehouse.external.dir;

  9. 经验证,参数 hive.create.as.external.legacy/hive.create.as.acid hive.create.as.insert.only/hive.txn.manager hive.ctas.external.tables/hive.external.table.purge.default/hive.default.fileformat.managed hive.metastore.warehouse.external.dir 都可以在客户端动态修改,但参数 hive.metastore.warehouse.external.dir 在客户端的动态修改并不生效,只能在服务端进行修改;

  10. LEGACY 传统模式下,Create table 建表语句,不指定存储格式和 TBLPROPERTIES 时,默认创建的是 ORC 格式的 Non ACID 外表,且是可 purge 的,即 TBLPROPERTIES('EXTERNAL'='TRUE',‘external.table.purge’=’TRUE’);

  11. LEGACY 传统模式下,创建 ORC 事务表,可以使用 HIVE3.X 新增的语法 CREATE MANAGED TABLE xyz(col1 type,...) type,...),来显示创建 managed table;

  12. 启用 Hive3 LEGACY 传统模式的方法有以下三种:

    系统级别静态设置: 配置 hive-site.xml 中参数 hive.create.as.external.legacy =true;

    会话级别静态设置: beeline -u jdbc:hive2://hostname:10000/default;hiveCreateAsExternalLegacy=true -n username -p password (即 url 中指定参数 hiveCreateAsExternalLegacy=true)

    会话级别动态设置: 在 beeline/hue 登录 hs2 并成功获取 session 后,执行以下命令: set hive.create.as.external.legacy=true;

  13. 可以通过以下命令,对已经创建完毕的表更改其 TBLPROPERTIES 属性:

    ALTER TABLE my_table UNSET TBLPROPERTIES ('transactional');

    ALTER TABLE … SET TBLPROPERTIES(‘EXTERNAL’=’TRUE’);

    ALTER TABLE … SET TBLPROPERTIES('transactional'='true',‘transactional_properties‘=‘insert_only’);

    ALTER TABLE … SET TBLPROPERTIES('transactional'='true',transactional_properties ='default');

周边生态如 SPARK/DATAX 如何对接 HIVE 3.x

  • SPARK SQL 和 datax 都不能直接读取 HIVE ACID 事务表(所谓直接读取,其底层是通过 HMS 获取到表底层的元数据后,绕过 HS2 直接读取 HDFS 上的数据文件),会报错。

  • Spark 和 datax 也都不能直接简单粗暴地将 orc 数据文件写到 orc 事务表对应的 hdfs 目录下 (此时底层绕过了 HS2 直接写文件到 HDFS 上),后续 HIVE SQL 查询时会报错:"bucketId out of range: 1";

  • SPARK SQL 和 DATAX 直接读写 HIVE ACID 事务表时会报错,底层原因是,HIVE 对 orc 事务表底层文件的目录结构和文件命名,有一套自己的规范(正如 MYSQL/ORACLE 对表底层文件的目录结构和文件命名有自己的一套规范,你不能绕过 MYSQL/ORACLE 服务,直接读写 NYSQL/ORACLE 表在本地文件系统中的文件一样);

  • HIVE 对 orc 事务表底层文件的目录结构和文件命名的规范是:文件都是 orc 格式;表目录下包括一个 base 子目录和一个或多个 delta 子目录;表底层文件名类似 base0000001_v0000001/bucket_00000, delta_0000001_0000001_0000/bucket_0000 和 delete_delta_0000001_0000001_0000/bucket_00000;

  • Spark 读写 HIVE ACID 事务表,推荐通过原 HortonWorks 开发并回馈给开源社区的插件 HWD: Hive WarehOUSE Connector;

  • 虽然 spark 通过 hwc 可以读写 Hive acid 事务表,但使用 spark hwd 基于 hive acid 事务表进行常规 etl/elt 操作,并不是最佳实践;

  • 如果仍需要使用 spark 进行 etl/elt 操作的话,建议使用 hive 外表,外表都是不 acid 事务表),此时 spark 不需要 hwc 可以直接对外表进行读写操作;

大数据应用对接 HIVE3.x 的几点建议

Hive 已经从早期一个简单的存储引擎之上的 SQL 解析层(单纯的 JAR 而没有服务),逐渐迭代优化,越来越像传统的关系型数据库了,对底层文件的目录结构文件名称存储格式等都由自己来管理,所以外部引擎的对接,尤其是对接 ACID 内部表,要尤其注意:

  • spark 读写 hive 的 orc 事务表,只能通过 hwc 的方式来;

  • 通过 spark 使用 hwc 读写 hive orc 事务表做各种 ETL/ELT 处理, 是错误的实践! Performing etl/elt in spark using hwc to extract large datasets from hive and then writing those back to hive via hwc is an ANTI-PATTEN!

  • 如果使用 spark 做 etl/elt 引擎构建数仓,应该基于 external 外部表来构建各层,建议在 hive 中通过 hive ddl 建外表,根据情况指定参数 hive.external.table.purge.default 和 hive.metastore.warehouse.external.dir ,或在表级别覆盖参数 TBLPROPERTIES(‘external.table.purge’=’TRUE‘):if spark is being used for etl/elt, consider staying with the external tables;

  • 如果使用 hive on tez 做 etl/elt 引擎构建数仓,建议使用 HIVE ACID 内部事务表,当然 ods/ads 层因为需要对接导入导出工具比如 spark/datax,仍只能使用 orc 非事务表(因为这些生态工具都不能直接访问 hive acid 事务内表);

  • spark 和 hive 互相访问对方的数据,推荐走 external 外部表的路线: the interaction between hive and spark,should be via external table;

  • 如果需要构建复杂的数据链路,使用的引擎包括 spark 和 hive 的话,建议 Integration layer 用 spark, serving layer 用 hive: use spark to ingest and curates the data, and implement a sweep location to build managed tables in hive for upstream analytics/reporting (present them using hive)

  • 内部表与外部表或外部文件进行交互,可以使用命令: Insert into/overwrite … select * from xxx; Load data inpath xxx into table xxx partition xxx;

Last updated