介绍
Hive 整合 HBase 的核心是通过 Hive 外部表映射 HBase 表,实现用 SQL 操作 HBase 中的 NoSQL 数据(无需数据迁移),既保留 HBase 的高并发读写特性,又利用 Hive 的 SQL 分析能力。
注意
- 数据类型:HBase 所有数据均以字节数组存储,Hive 表建议全部定义为 STRING 类型,避免类型转换错误;
- 表类型:必须创建 Hive 外部表(EXTERNAL),否则删除 Hive 表会同步删除 HBase 表;
- 读写权限:Hive 运行用户需有 HBase 表的读写权限(HBase 权限:
grant 'hive', 'RW', 'student'); - 事务支持:Hive 整合 HBase 不支持事务,避免并发写入导致数据冲突;
- 适用场景:适合「HBase 存储明细数据 + Hive 做批量分析」,不适合高并发实时查询(直接用 HBase API 更优)。
整合原理
Hive 与 HBase 的整合依赖 HBaseStorageHandler 组件,本质是:
- 元数据映射:Hive 外部表的字段与 HBase 表的「列族:列名」一一绑定;
- 数据路由:Hive 执行 SQL 时,通过 StorageHandler 调用 HBase Java API 读写 HBase 数据;
- 无数据拷贝:Hive 表仅存储元数据,实际数据仍在 HBase 中,两者实时同步。
整合方式一(推荐)
修改 hive-site.xml 文件
vim /program/hive-3.1.2/conf/hive-site.xml
在末尾增加下面配置:
<!-- 集成HBase:开始 -->
<!-- 指定zookeeper,因为HBase需要zookeeper -->
<property>
<name>hive.zookeeper.quorum</name>
<value>hadoop1:2181,hadoop2:2181,hadoop3:2181</value>
</property>
<!-- 添加 HBase jar包 -->
<property>
<name>hive.aux.jars.path</name>
<value>
file:///program/hbase-2.1.9/lib/hbase-common-2.1.9.jar
file:///program/hbase-2.1.9/lib/hbase-client-2.1.9.jar
file:///program/hbase-2.1.9/lib/hbase-server-2.1.9.jar
file:///program/hbase-2.1.9/lib/hbase-hadoop2-compat-2.1.9.jar
file:///program/hbase-2.1.9/lib/netty-all-4.0.23.Final.jar
file:///program/hbase-2.1.9/lib/hbase-protocol-2.1.9.jar
file:///program/hbase-2.1.9/lib/zookeeper-3.4.10.jar
</value>
</property>
<!-- 集成HBase:结束 -->
整合方式二
将 HBase 的核心配置文件拷贝到 Hive 的 conf 目录(所有 Hive 节点):
# 拷贝HBase配置到Hive
cp $HBASE_HOME/conf/hbase-site.xml $HIVE_HOME/conf/
关键配置 hbase-site.xml:
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop1,hadoop2,hadoop3</value> <!-- ZK集群地址 -->
</property>
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value> <!-- ZK端口 -->
</property>
依赖包
Hive 的 lib 目录需包含 HBase 相关依赖包(若缺失,从 HBase 的 lib 拷贝):
将下面 jar 包拷贝到 Hive 的 lib 目录:
/program/hbase-2.1.9/lib/hbase-common-2.1.9.jar
/program/hbase-2.1.9/lib/hbase-client-2.1.9.jar
/program/hbase-2.1.9/lib/hbase-server-2.1.9.jar
/program/hbase-2.1.9/lib/hbase-hadoop2-compat-2.1.9.jar
/program/hbase-2.1.9/lib/netty-all-4.0.23.Final.jar
/program/hbase-2.1.9/lib/hbase-protocol-2.1.9.jar
/program/hbase-2.1.9/lib/zookeeper-3.4.10.jar
建表方式一:Hive 创建外部表
必须先在 HBase 中创建表,然后在 Hive 中创建外部表,并映射 HBase 表
HBase 创建表(先有 HBase 表)
进入HBase Shell:
hbase shell
创建HBase表:表名 student,列族 info(可多列族)
create 'student', 'info'
插入测试数据(行键1001,列族info,列name/age/sex)
put 'student', '1001', 'info:name', '张三'
put 'student', '1001', 'info:age', '20'
put 'student', '1001', 'info:sex', '男'
put 'student', '1002', 'info:name', '李四'
put 'student', '1002', 'info:age', '21'
put 'student', '1002', 'info:sex', '女'
查看数据:
scan 'student'
Hive 创建表
CREATE EXTERNAL TABLE student_hive_hbase (
rowkey STRING, -- 必须映射HBase的行键(名称可自定义,需和下方rowkey对应)
name STRING, -- 映射info:name
age STRING, -- 映射info:age
sex STRING -- 映射info:sex
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' -- 核心Handler
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name,info:age,info:sex' -- 映射规则
)
TBLPROPERTIES (
'hbase.table.name' = 'student_hive_hbase' -- 关联的HBase表名
);
映射规则说明(hbase.columns.mapping)
| Hive 字段 | HBase 映射规则 | 说明 |
|---|---|---|
| rowkey | :key |
固定写法,映射HBase行键 |
| name | info:name |
映射列族info的列name |
| age | info:age |
映射列族info的列age |
建表方式二: hive创建管理表(内部表)
通过 hive创建管理表(内部表),会自动在 hbase 创建表
注意:由于是管理表(内部表),通过 hive 删除表时,也同时删除 hbase 中的表,生产环境中较少使用
CREATE EXTERNAL TABLE student_hive_hbase (
rowkey STRING, -- 必须映射HBase的行键(名称可自定义,需和下方rowkey对应)
name STRING, -- 映射info:name
age STRING, -- 映射info:age
sex STRING -- 映射info:sex
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' -- 核心Handler
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name,info:age,info:sex' -- 映射规则
)
TBLPROPERTIES (
'hbase.table.name' = 'student_hive_hbase' -- 关联的HBase表名
);
映射规则说明(hbase.columns.mapping)
| Hive 字段 | HBase 映射规则 | 说明 |
|---|---|---|
| rowkey | :key |
固定写法,映射HBase行键 |
| name | info:name |
映射列族info的列name |
| age | info:age |
映射列族info的列age |
插入数据
INSERT INTO student_hive_hbase VALUES ('1001', '张三', '20', '男');
INSERT INTO student_hive_hbase VALUES ('1002', '李四', '21', '女');
执行 mapreduce 插入数据
hive查询数据
select * from student_hive_hbase;
执行结果:
1001 张三 20 男
1002 李四 21 女
hbase查询数据
启动 hbase shell,执行下面命令:
scan 'student_hive_hbase',{FORMATTER => 'toString'}
执行结果:
1001 column=info:age, timestamp=1765073576636, value=20
1001 column=info:name, timestamp=1765073576636, value=张三
1001 column=info:sex, timestamp=1765073576636, value=男
1002 column=info:age, timestamp=1765073593222, value=21
1002 column=info:name, timestamp=1765073593222, value=李四
1002 column=info:sex, timestamp=1765073593222, value=女
hive删除表
由于是管理表(内部表),通过 hive 删除表时,也同时删除 hbase 中的表,生产环境中较少使用
drop table student_hive_hbase;
查看 HBase 中的 student_hive_hbase 表:
scan 'student_hive_hbase'
查询报错,提示表不存在,如下:
Hive SQL 操作 HBase 数据
查询数据(最常用)
-- 查所有数据
SELECT * FROM student_hive_hbase;
-- 条件查询(行键/字段过滤)
SELECT rowkey, name, age FROM student_hive_hbase WHERE rowkey = '1001';
SELECT rowkey, name FROM student_hbase WHERE age > '20';
预期结果:
| rowkey | name | age | sex |
|---|---|---|---|
| 1001 | 张三 | 20 | 男 |
| 1002 | 李四 | 21 | 女 |
插入数据(Hive → HBase)
-- 插入单行
INSERT INTO student_hive_hbase VALUES ('1003', '王五', '22', '男');
-- 批量插入(从其他Hive表导入)
INSERT INTO student_hive_hbase
SELECT '1004', name, age, sex FROM other_table WHERE id = 1004;
插入后在 HBase 验证:scan 'student' 可看到 1003/1004 行数据。
更新数据(通过覆盖插入)
Hive 无直接 UPDATE 语法,需通过 INSERT OVERWRITE 或单行插入覆盖:
-- 覆盖更新1001行的age
INSERT INTO student_hive_hbase VALUES ('1001', '张三', '23', '男');
删除数据
Hive 无直接 DELETE 语法,需通过 HBase Shell 或 HBase API 删除:
# HBase Shell删除行键1004
deleteall 'student', '1004'
验证数据一致性
-- Hive中查询
SELECT * FROM student_hive_hbase WHERE rowkey = '1003';
-- HBase中查询
hbase(main):001:0> get 'student', '1003'
两者结果需完全一致,说明映射正常。
进阶用法
映射多列族 HBase 表
若 HBase 表有多个列族(如 info、score),Hive 表映射如下:
CREATE EXTERNAL TABLE student_hbase_multi (
rowkey STRING,
name STRING, -- info:name
age STRING, -- info:age
math INT, -- score:math
english INT -- score:english
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name,info:age,score:math,score:english'
)
TBLPROPERTIES ('hbase.table.name' = 'student');
分区表映射(优化查询)
对大数据量 HBase 表,可在 Hive 中创建分区表:
CREATE EXTERNAL TABLE student_hbase_part (
rowkey STRING,
name STRING,
age STRING
)
PARTITIONED BY (dt STRING) -- 按日期分区
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name,info:age'
)
TBLPROPERTIES ('hbase.table.name' = 'student');
-- 添加分区(分区仅作用于Hive,不影响HBase)
ALTER TABLE student_hbase_part ADD PARTITION (dt='20250101');
自定义序列化/反序列化
若 HBase 数据是二进制/自定义格式,可指定 SERDE:
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name',
'serialization.format' = '1', -- 序列化格式
'hbase.serde.class' = 'org.apache.hadoop.hive.hbase.HBaseSerDe' -- 自定义SerDe
)
常见问题
1. 报错:Cannot connect to ZooKeeper
- 原因:Hive 未读取到 HBase 的 ZK 配置;
- 解决方案:确认
hbase-site.xml已拷贝到 Hive conf,且 ZK 地址正确,ZK 集群正常运行。
2. 报错:Unknown column family info
- 原因:Hive 映射的列族/列名与 HBase 表不一致;
- 解决方案:执行
list/describe 'student'确认 HBase 表的列族名称。
3. Hive 查询数据为空,但 HBase 有数据
- 原因1:行键/列名大小写不一致(HBase 大小写敏感,Hive 不敏感);
- 原因2:Hive 表字段类型与 HBase 数据类型不兼容(如 HBase 是字符串,Hive 定义为 int);
- 解决方案:统一大小写,字段类型全部先设为 STRING(HBase 数据默认是字符串)。
4. 插入数据后 HBase 无数据
- 原因:Hive 插入操作触发 MapReduce 任务,需等待任务完成;
- 解决方案:执行
yarn application -list查看任务状态,或直接用INSERT OVERWRITE替代INSERT INTO。
5. 性能问题:Hive 查询 HBase 慢
- 优化1:限定行键范围(HBase 行键是有序的,避免全表扫描);
- 优化2:禁用 Hive 并行执行:
set hive.exec.parallel=false; - 优化3:调整 HBase 扫描缓存:
set hbase.client.scanner.caching=1000。
总结
Hive 整合 HBase 的核心是通过外部表+StorageHandler 实现元数据映射,关键步骤:
- 同步配置文件和依赖包;
- HBase 创建表并插入数据;
- Hive 创建外部表绑定 HBase 表;
- 用 Hive SQL 分析 HBase 数据。
参考:
https://blog.csdn.net/Yian123456/article/details/143986749
