问题描述

Pasted image 20231220150234.png

原因排查

HDP 的 hive 使用的版本较高为3.1.0  ,默认建表都是使用 ACID 的事务表。而 HDP的spark版本较低为2.3 目前还不支持 hive 的 ACID 功能,因此无法读取 ACID 表的数据,准确来说是内表的数据。

官方资料

spark issues 地址: SPARK-15348 Hive ACID

解决方案

修改hive以下配置,重启hive

hive.strict.managed.tables =false
hive.create.as.insert.only =false
metastore.create.as.acid =false

Pasted image 20231220150309.png

Pasted image 20231220150319.png

Pasted image 20231220150325.png

其他资料

Hive 中支持的表类型和 ACID 特性

表类型 ACID 文件格式 插入 更新 / 删除
托管表:CRUD 事务 ORC
托管表:仅插入式事务 任意格式 没有
托管表:临时 没有 任意格式 没有
外部表 没有 任意格式 没有

查看表的属性,指令:desc formatted tb_name

非 ACID 表:

| Table Type: | MANAGED_TABLE | NULL | | Table Parameters: | NULL | NULL | | | COLUMN_STATS_ACCURATE | {"BASIC_STATS":"true"} | | | numFiles | 36554 | | | numPartitions | 4582 | | | numRows | 656353471 | | | rawDataSize | 3687190343914 | | | totalSize | 191558565757 | | | transient_lastDdlTime | 1626229162 |

ACID 表:

| Table Type: | MANAGED_TABLE | NULL | | Table Parameters: | NULL | NULL | | | bucketing_version | 2 | | | comment | 交易日志表 | | | numFiles | 2131 | | | numPartitions | 2131 | | | numRows | 1303371497 | | | rawDataSize | 0 | | | totalSize | 669842162666 | | | transactional | true | | | transactional_properties | insert_only | | | transient_lastDdlTime | 1613705157 |

其中:

  • transactional=true,标识为事务表
  • transactional_properties=insert_only

事务表的适用场景

对于数仓中的行级数据更新删除需求比较频繁的,可以考虑使用事务表。

但平常的 hive 表并不建议使用事务表。因为事务表的限制很多,加上由于 hive 表的特性,也很难满足高并发的场景。

另外,如果事务表太多,并且存在大量的更新操作,metastore 后台启动的合并线程会定期的提交 MapReduce Job,也会一定程度上增重集群的负担。

结论: 除非有非常迫切的行级更新需求,又只能用 hive 表来做,才需要去考虑事务表。

注意事项

  1. 不支持 BEGIN、COMMIT、ROLLBACK 等语句,所有的语句都是自动提交
  2. 仅支持 ORC 格式

设计原理与实现

文件管理格式

HDFS 本身是不支持直接修改文件的, 也不能保证有人追加内容时的读一致性。

因此,为了支持 ACID 的特性,Hive 只能使用其他数据仓库常用的方法,也就是增量的形式记录更新和删除(也称做读时更新)。

存储在事务表中的数据会被分成两种类型的文件:

base 文件,用来存放平常的数据
delta 文件,用来存储新增、更新、删除的数据。每一个事务处理数据的结果都会单独新建一个 delta 文件夹用来存储数据。
在有用户要读取这个表的数据时,就会将 base 文件和 delta 文件都读取到内存,然后进行合并(就是判断哪些记录有被修改,哪些记录被删除等)。

ACID 表的文件结构:${Hive_path}/db/table_name/base_{id}/file。

Found 2 items | | -rw-rw—-+ 3 hdfs hadoop 1091048351 2021-07-13 15:00 /warehouse/tablespace/managed/hive/db_name.db/tb_name/date=2021-06-30/base_0002252/000000_0 | -rw-rw—-+ 3 hdfs hadoop 1091048351 2021-07-13 15:00 /warehouse/tablespace/managed/hive/db_name.db/tb_name/date=2021-06-30/delta_0000023_0000023_0000/000000_0

其中0000023标识事务 ID,0000 表示序号,从上面的表中我们可以看到有一个事务的数据还未合并成 base。

非 ACID 表,通过别的表格导入数据,文件目录为:

+—————————————————-+ | DFS Output | +—————————————————-+ | 2.6 M 7.9 M /warehouse/tablespace/managed/hive/db_name.db/tb_name/day=2021-07-18/-ext-10000/000000_0 | +—————————————————-+

普通内部表文件目录:

+—————————————————-+ | DFS Output | +—————————————————-+ | 7.4 M 22.1 M /warehouse/tablespace/managed/hive/db_name.db/tb_name/day=2021-07-18/000000_0 | +—————————————————-+