这是CDP中Apache Hive3用户指南系列之一,之前的文章请参考<CDP的Hive3系列之Hive Metastore介绍>,<CDP中的Hive3系列之Apache Hive3的特性>,<CDP中的Hive3系列之启动Apache Hive3>和<CDP中的Hive3系列之Hive3使用指南>
1 ACID操作
Apache Hive 在行级别支持 ACID(原子性、一致性、隔离性和持久性)v2 事务,无需任何配置。了解此支持需要什么可帮助您确定您创建的表类型。
默认情况下,托管表是 ACID 表。您不能在托管表上禁用ACID 事务,但您可以更改 Hive 默认行为以默认创建外部表以模仿旧版本的Hive行为。应用程序开发和操作通过强大的事务保证和 SQL 命令的简单语义得到简化。您不需要存储 ACID v2 表,因此维护更容易。随着事务语义的改进,可以使用高级优化,例如物化视图重写和自动查询缓存。通过这些优化,您可以部署新的 Hive 应用程序类型。
Hive 操作是原子的。操作要么完全成功,要么失败;它不会导致部分数据。Hive操作也是一致的:应用程序执行操作后,结果在每个后续操作中对应用程序都是可见的。Hive 操作是隔离的。您的操作不会对其他用户造成意外的副作用。最后,Hive 操作是持久的。已完成的操作会在发生故障时保留。
Hive 操作在行级别而不是表或分区级别是原子的。一个 Hive 客户端可以在另一个客户端向该分区添加行的同时从一个分区读取。事务流将数据快速插入 Hive 表和分区。
1.1 为事务配置分区
您设置了几个参数,以防止或允许动态分区,即在表上隐式创建的分区中插入、更新或删除数据。
配置分区涉及更改以下参数以满足您的需要:
· hive.exec.max.dynamic.partitions
· hive.exec.max.dynamic.partitions.pernode
您设置hive.exec.dynamic.partition.mode为strict 以防止动态分区或设置为 nonstrict(默认值)以在事务应用程序中包含INSERT、UPDATE 和DELETE 语句。
1) 在Cloudera Manager > Clusters 中选择 Hive 服务。单击Configuration,然后搜索hive-site.xml。
2) 在 hive-site.xml 的 HiveServer2 高级配置片段(安全阀)中,单击 + 并添加hive.exec.dynamic.partition.mode属性。
3) 将值设置为nonstrict。
4) 保存更改并重新启动 Hive 服务。
1.2 查看事务
作为管理员,您可以查看打开和中止事务的列表。
输入查询以查看事务。
SHOW TRANSACTIONS
输出中会显示以下信息:
· 事务编号
· 事务状态
· 发起事务的 Hive 用户
· 发起事务的主机或虚拟机
1.3 查看事务锁
作为 Hive 管理员,您可以获得有关表、分区或Schema上的锁的故障排除信息。
默认情况下Hive 事务是启用状态,这会禁用Zookeeper 锁定。Hive Metastore 中的DbLockManager会存储和管理所有事务锁信息。心跳会定期从锁持有者和事务发起者发送到 Hive Metastore,以防止过时的锁和事务。如果 Metastore 在hive.txn.timeout配置属性指定的时间内没有收到心跳,则锁定或事务将被中止 。检查事务是否已启用(默认)。
1) 输入 Hive 查询以检查表锁。
SHOW LOCKS mytable EXTENDED;
2) 检查分区锁。
SHOW LOCKS mytable PARTITION(ds='2018-05-01', hr='12') EXTENDED;
3) 检查Schema锁。
SHOW LOCKS SCHEMA mydatabase;
除非使用 ZooKeeper 或内存中锁管理器,否则输出中会出现以下信息。
· 数据库名称
· 表名
· 分区,如果表已分区
· 锁定状态:
n Acquired - 事务发起者持有锁
n Waiting - 事务发起者正在等待锁定
n Aborted - 锁已超时但尚未清除
· 锁类型:
n Exclusive - 不能共享锁
n Shared_read - 该锁不能与任何数量的其他 shared_read 锁共享
n Shared_write - 该锁可以由任意数量的其他 shared_read 锁共享,但不能与其他 shared_write 锁共享
· 与锁关联的事务 ID(如果存在)
· 最后一次锁持有者发送了一个心跳
· 获取锁的时间(如果已获取)
· 请求锁定的 Hive 用户
· Hive 用户在其上运行 Hive 客户端的主机或虚拟机
· Blocked By ID - 导致当前锁处于等待模式的锁的 ID,如果锁处于此模式
2 数据压缩
作为管理员,您需要管理在数据摄取期间累积的增量文件的压缩。压缩是一个执行文件关键内务处理的过程。
Hive 为每个更改表或分区的事务创建一组增量文件,并将它们存储在单独的增量目录中。默认情况下,Hive 会定期自动压缩增量文件和基本文件。压缩是文件的合并。您可以配置自动压缩,以及对基本文件和增量文件执行手动压缩。为了提交压缩任务,Hive使用Tez作为执行引擎,并在Stack中使用MapReduce算法。压缩发生在后台,不会影响并发读写。压缩启动器应该只在一个 HMS实例上运行。
有两种类型的压缩:
· 次要压缩
将一组增量文件重写为存储桶的单个增量文件。
· 主要压缩
将一个或多个增量文件和基本文件重写为存储桶的新基本文件。
2.1 启用自动压缩
必须设置 Hive 和 Hive Metastore 服务配置中的几个属性才能启用自动压缩。您需要检查属性设置是否正确,并将其中一项属性添加到 Hive on Tez 服务。然后将定期进行自动压实,但仅在必要时进行。
必须在 Hive Metastore (Hive-1) 和 Hive-on-Tez 服务中设置以下属性,如下所示:
· hive.compactor.initiator.on = true (默认)
· hive.compactor.worker.threads = <大于 0 的值>(默认值和推荐值 = 5)
· hive.metastore.runworker.in = hs2 (默认)
您正在压缩的文件必须是 ORC 格式。
1) 在 Cloudera Manager 中,选择 Hive Metastore 服务:Clusters > Hive-1 > Configuration。
2) 搜索compact。
3) 检查 Turn on Compactor Initiator Thread ( hive.compactor.initiator.on),Number of Threads Used by Compactor ( hive.compactor.worker.threads) 和 Run Compactor on Hive Metastore or HiveServer2 ( hive.metastore.runworker.in) 是否设置为上面显示的值。
4) 保存更改。
5) 在 Cloudera Manager 中,选择 Hive Metastore 服务:Clusters > HIVE_ON_TEZ-1 > Configuration。
6) 搜索compact。
7) 检查 Compactor 使用的线程数 ( hive.compactor.worker.threads) 和在 Hive Metastore 或 HiveServer2 上运行压缩器 ( hive.metastore.runworker.in) 是否设置为 hs2。
8) 保存更改并在适当的时候重新启动 Hive on Tez 和 Hive (HIVE-1) Metastore 服务。
2.2 手动启动压缩
当自动压缩由于某种原因失败时,您手动启动压缩。您可以通过运行 Hive 语句开始压缩。
仔细考虑是否需要进行大型压缩,因为此过程会消耗大量系统资源并需要很长时间。在低流量期间启动主要压缩。表或分区的基本文件和增量文件被压缩。
使用查询开始压缩
您可以使用以下语法发出开始压缩的查询:
ALTER TABLE tablename [PARTITION (partition_key='partition_value' [,...])] COMPACT 'compaction_type'
您正在压缩的文件必须是 ORC 格式。
1) 在 Cloudera Manager 中,选择 Hive Metastore 服务:Clusters > Hive-1 > Configuration。
2) 搜索compact。
3) 检查是否选择了 Hive Metastore 服务器默认组 ( hive.compactor.initiator.on=true)。
4) 执行查询以启动表的主要压缩。
ALTER TABLE mytable COMPACT 'major'
即使设置了 NO_AUTO_COMPACTION 表属性,ALTER TABLE 也会压缩表。
2.3 查看压缩进度
您可以通过运行 Hive 查询来查看压缩的进度。
输入查询以查看压缩的进度。
SHOW COMPACTIONS;
· 唯一的内部 ID
· 数据库名称
· 表名
· 分区名称
· 主要或次要压缩
· 压缩状态:
- 已启动 - 在队列中等待
- 工作 - 目前正在压缩
- 准备好清理 - 压缩完成并计划删除旧文件
- 失败 - 作业失败。详细信息会打印到 Metastore 日志中。
- 成功
- Attempted - 发起者试图安排一个压缩,但失败了。详细信息会打印到 Metastore 日志中。
· 线程 ID
· 压缩开始时间
· 期间
· 作业 ID - 提交的 MapReduce 作业的 ID
2.4 禁用自动压缩
您可以通过设置 Hive 表属性来禁用特定 Hive 表的自动压缩。默认情况下,压缩已启用,因此您必须输入 ALTER TABLE 命令以禁用它。
禁用自动压缩不会阻止您执行手动压缩。
启动 Hive shell,并在目标表的数据库中,更改 TBLPROPERTIES。
ALTER TABLE my_t SET TBLPROPERTIES ('NO_AUTO_COMPACTION'='true');
2.5 压缩属性
您检查并更改了许多 Apache Hive 属性,以配置数据摄取期间累积的增量文件的压缩。您需要知道默认值、有效值以及设置这些属性的位置:Cloudera Manager、TBLPROPERTIES、hive-site.xml 或 core-site.xml。当 Cloudera Manager 对运行时服务的配置属性搜索中没有出现属性时,您可以使用 Cloudera Manager 安全阀将该属性添加到 hive-site 或 core-site。
2.5.1 压缩的基本属性
hive.compactor.initiator.on
默认=false
是否在这个 Metastore 实例上运行启动器和清理器线程。
hive.compactor.worker.threads
默认=0
将此设置为正数以启用 Hive 事务,这是触发事务所必需的。工作线程产生作业来执行压缩,但不执行压缩本身。增加工作线程的数量会减少压缩表或分区所需的时间。但是,增加工作线程的数量也会增加 CDP 集群的后台负载,因为它们会导致更多的作业在后台运行。
hive.metastore.runworker.in
默认=HS2
指定在哪里运行生成作业以执行压缩的工作线程。有效值为 HiveServer (HS2) 或 Hive Metastore (HMS)。
hive.compactor.abortedtxn.threshold
默认值=1000
涉及将触发主要压缩的给定表或分区的中止事务的数量。
2.5.2 高级的压缩属性
hive.compactor.worker.timeout
默认值=86400s
期望时间值的单位(d/day, h/hour, m/min, s/sec, ms/msec, us/usec, ns/nsec),如果未指定,则为 sec。压缩作业将被宣布失败并且压缩重新排队的时间(以秒为单位)。
hive.compactor.check.interval
默认=300s
有效值是带有单位(d/day、h/hour、m/min、s/sec、ms/msec、us/usec、ns/nsec)的时间,如果未指定,则为 sec。
检查之间的时间(以秒为单位)以查看是否需要压缩任何表或分区。这个值应该保持很高,因为每次检查压缩都需要对NameNode 进行多次调用。减少此值可减少为需要它的表或分区开始压缩所需的时间。但是,检查是否需要压缩需要对自上次主要压缩以来完成的事务中涉及的每个表或分区多次调用 NameNode。因此,减小此值会增加 NameNode 上的负载。
hive.compactor.delta.num.threshold
默认值=10
表或分区中触发次要压缩的增量目录数。
hive.compactor.delta.pct.threshold
默认值=0.1
增量文件相对于触发主要压缩的基数的百分比(小数)大小。(1.0 = 100%,所以默认值 0.1 = 10%。)
hive.compactor.max.num.delta
默认值=500
压缩器尝试在单个作业中处理的最大增量文件数。
hive.compactor.wait.timeout
默认值=300000
该值必须大于 2000 毫秒。
阻塞压缩的超时时间(以毫秒为单位)。
hive.compactor.initiator.failed.compacts.threshold
默认值=2
有效值介于 1 到 20 之间,并且必须小于hive.compactor.history.retention.failed。
连续压缩失败的次数(每个表/分区),之后不再安排自动压缩。
hive.compactor.cleaner.run.interval
默认值=5000ms
有效值是带单位的时间(d/day、h/hour、m/min、s/sec、ms/msec、us/usec、ns/nsec),如果未指定,则为 msec。
清洁线程运行之间的时间。
hive.compactor.job.queue
指定向其提交压缩作业的 Hadoop 队列名称。如果值为空字符串,Hadoop 将选择队列。
hive.compactor.compact.insert.only
默认=true
压缩器压缩仅插入表,或不压缩(假)。一个安全开关。
hive.compactor.crud.query.based
默认=false
对完整的 CRUD 表执行主要压缩作为查询,并禁用次要压缩。
hive.split.grouping.mode
默认=query
有效值为query或compactor。
此属性在基于查询的压缩器中设置为压缩器。此设置使 Tez SplitGrouper 能够根据存储桶编号对拆分进行分组,以便同一存储桶编号的不同存储桶文件中的所有行在压缩后都可以在同一个存储桶文件中结束。
hive.compactor.history.retention.succeeded
默认=3
有效值介于 0 和 100 之间。
确定给定表/分区的压缩历史记录中保留了多少成功的压缩记录。
hive.compactor.history.retention.failed
默认=3
有效值介于 0 和 100 之间。
确定给定表/分区的压缩历史记录中保留了多少失败的压缩记录。
hive.compactor.history.retention.attempted
默认值=2
有效值介于 0 和 100 之间。
确定给定表/分区的压缩历史记录中保留了多少尝试压缩记录。
hive.compactor.history.reaper.interval
默认=2m
有效值是带单位的时间(d/day、h/hour、m/min、s/sec、ms/msec、us/usec、ns/nsec),如果未指定,则为 msec。
确定压缩历史收割者运行的频率。
3 查询矢量化
您可以使用矢量化来改进指令管道和缓存使用。矢量化使某些数据和查询能够处理整列而不是一次一行的原始类型的批次。
3.1 矢量化介绍
矢量化查询执行批量处理 Hive 数据,将大量的行数据导入列,而不是中间结果。这种技术比存储临时文件的 MapReduce 执行过程更有效。
3.2 不支持的矢量化数据功能
矢量化数据不支持某些功能:
· DDL 查询
· 单表以外的 DML 查询,只读查询
· 优化行列式 (ORC) 以外的格式
3.3 矢量化数据支持的功能
矢量化数据支持以下功能:
· 单表,只读查询
支持选择、过滤和分组数据。
· 分区表
· 以下表达式:
- 比较:>、>=、<、<=、=、!=
- 算术加、减、乘、除和取模
- 逻辑与和或
- 聚合 sum、avg、count、min 和 max
3.4 支持的数据类型
您可以使用矢量化查询查询以下类型的数据:
· tinyint
· smallint
· int
· bigint
· date
· boolean
· float
· double
· timestamp
· stringchar
· varchar
· binary
3.5 启用矢量化
默认情况下禁用查询矢量化。作为管理员,您可以使用 Cloudera Manager 启用查询矢量化的可能性。
发出查询后,Hive 会检查查询和数据以确定是否可以进行矢量化。如果没有,Hive 将在禁用矢量化的情况下执行查询。
1) 在Cloudera Manager > Clusters 中选择 Hive 服务。单击配置,然后搜索hive.vectorized.execution.enabled。
2) 接受默认值(已启用),或选中HiveServer2 默认组以启用该属性。
3) 点击保存。
4) 单击操作>部署客户端配置。
5) 重启Hive。
3.6 配置查询矢量化
您可以通过在 Cloudera Manager 中设置属性来管理查询矢量化。每个属性的名称及其描述有助于设置矢量化。
3.6.1 矢量化属性
hive.vectorized.groupby.checkinterval
在矢量化分组方式中,在重新检查平均变量大小以估计内存使用情况之前添加到哈希表的行条目数。
hive.vectorized.groupby.flush.percent
超过内存阈值时刷新的矢量化分组聚合散列中条目的 0.0 和 1.0 之间的比率。
hive.vectorized.execution.enabled
启用优化,通过一次处理 1024 行的块来简化操作,从而矢量化查询执行。
hive.vectorized.execution.reduce.enabled
是否对查询执行的reduce 端进行矢量化。
hive.vectorized.use.vectorized.input.format
如果启用,Hive 会在可用时使用本机矢量化输入格式进行矢量化查询执行。
hive.vectorized.use.checked.expressions
为了提高性能,矢量化表达式使用宽数据类型(如 long 和double)进行操作。使用宽数据类型时,矢量化表达式的表达式计算过程中可能会发生数值溢出,其方式与非矢量化表达式不同。因此,与非矢量化表达式返回的结果相比,矢量化表达式返回的查询结果可能不同。启用此配置后,Hive 使用矢量化表达式来处理数字溢出,其方式与处理非矢量化表达式的方式相同。
hive.vectorized.adaptor.usage.mode
矢量化适配器使用模式指定矢量化引擎尝试矢量化没有本机矢量化版本可用的 UDF 的程度。选择“none”选项指定仅使用本机矢量化 UDF 的查询被矢量化。选择“选择”选项指定 Hive 选择使用矢量化适配器基于性能优势对 UDF 的子集进行矢量化。选择“all”选项指定矢量化适配器用于所有 UDF,即使在本机矢量化版本不可用时也是如此。
hive.vectorized.use.vector.serde.deserialize
如果启用,Hive 使用内置的矢量 SerDes 来处理文本和序列文件表以进行矢量化查询执行。
hive.vectorized.input.format.excludes
指定要从使用矢量化输入格式的矢量化查询执行中排除的文件输入格式类名列表。请注意,根据是否启用了行 SerDes 或矢量 SerDes,对于排除的输入格式,仍然可以进行矢量化执行。
3.7 检查查询执行
您可以通过运行 EXPLAIN VECTORIZATION 查询语句来确定在执行期间是否发生了查询矢量化。
1) 从 Beeline 启动 Hive。
$ hive
2) 将 hive.explain.user 设置为 false 以查看矢量值。
SET hive.explain.user=false;
3) 对您希望 CDP 使用矢量化处理的查询运行 EXPLAIN VECTORIZATION 语句。
EXPLAIN VECTORIZATION SELECT COUNT(*) FROM employees where emp_no>10;
以下输出确认发生了矢量化:
+----------------------------------------------------+ | Explain | +----------------------------------------------------+ | Plan optimized by CBO. | | | | Vertex dependency in root stage | | Reducer 2 <- Map 1 [CUSTOM_SIMPLE_EDGE] *vectorized* | | File Output Operator [FS_14] | | Group By Operator [GBY_13] (rows=1 width=12) | | Output:["_col0"],aggregations:["count(VALUE._col0)"] | | <-Map 1 [CUSTOM_SIMPLE_EDGE] vectorized | | PARTITION_ONLY_SHUFFLE [RS_12] | | Group By Operator [GBY_11] (rows=1 width=12) | | Output:["_col0"],aggregations:["count()"] | | Select Operator [SEL_10] (rows=1 width=4) | | Filter Operator [FIL_9] (rows=1 width=4) | | predicate:(emp_no > 10) | | TableScan [TS_0] (rows=1 width=4) | | default@employees,employees,Tbl:COMPLETE,Col:NONE,Output:["emp_no"] | | | +----------------------------------------------------+ 23 rows selected (1.542 seconds)
4 跟踪Hive on Tez 查询执行
您需要知道如何在执行期间监控 Hive on Tez 查询。一些工具提供查询详细信息,例如执行时间。
假设您启用了提取任务,您可以从 HiveServer (HS2) 日志中检索有关查询的本地提取详细信息。您可以配置以下属性:
hive.fetch.task.conversion
值: minimal
一些选择查询可以转换为单个 FETCH 任务而不是MapReduce 任务,从而最大限度地减少延迟。none 值禁用所有转换,minimum 转换简单查询,例如 SELECT * 和对分区列的筛选,more 转换 SELECT 查询,包括FILTERS。
hive.fetch.task.conversion.threshold
值: 1 GiB
超过此大小,查询将转换为获取任务。
增加静态池不会加快读取速度,不建议这样做。
1) 在 Cloudera Manager 中,单击Clusters > Hive on Tez > Configuration,然后搜索fetch。
2) 接受或更改提取任务属性的默认值。
3) 导航到 HiveServer 日志目录并查看日志文件。
在 Cloudera Manager 中,您可以找到该目录的位置作为 HiveServer2 Log Directory 的值。
4) 在 Cloudera Manager 中,单击Clusters > Hive on Tez > Configuration,然后单击 HiveServer Web UI。
5 在 YARN 中跟踪 Apache Hive 查询
您需要知道如何在 YARN 中监控 Apache Hive 查询。使用 Beeline 中查询执行的输出信息,您可以完成此任务。
1) 在 Beeline 中运行查询。
0: jdbc:hive2://ip-10-10-10-10.cloudera.site:> select * from depts; INFO : Compiling command(queryId=hive_1599978188515_5723b397-c375-48c2-ab38-7be298603de9): select * from depts ...
2) 向下滚动输出,直到找到包含 YARN App id 的 INFO。
... INFO : Status: Running (Executing on YARN cluster with App id application_1599978188515_0010) ---------------------------------------------------------------------------------------------- VERTICES MODE STATUS TOTAL COMPLETED RUNNING PENDING FAILED KILLED ---------------------------------------------------------------------------------------------- ...
3) 在 Cloudera Manager 中,单击集群> Yarn >实例> Web UI。
4) 单击资源 Web UI >应用程序
5) 找到 App id 的匹配项并收集您想要的信息。
6 应用程序未运行消息
了解在YARN的应用程序日志中显示的来自Tez的消息Application not running可防止在检查 Hive 查询时出现混淆。
在启动期间,HiveServer 启动可用的会话,直到 tez.session.am.dag.submit.timeout.secs过期,然后应用程序主服务器被杀死。当您运行另一个查询时,HiveServer 会根据需要透明地重新启动死的 AM。HiveServer尝试在关闭期间清除 Tez 池中的会话。堆栈跟踪日志中的“应用程序未运行”消息不是问题。此消息只是在会话关闭或重新启动且 AM 超时时记录的跟踪。