本文是大数据系列第 36 篇,介绍 HBase 列族设计思路与 Shell 下的增删改查实操。
列族(Column Family)
HBase 中列的完整标识为 列族名:限定符(Column Family : Qualifier),列族是最小的物理存储单元。同一列族的数据存储在同一组 HFile 中,读写时以列族为单位刷写磁盘。
列族数量的抉择
列族数量过多会带来以下问题:
- MemStore 刷写频繁:每个列族都有独立的 MemStore,小列族触发 flush 时会连带刷写其他列族,产生大量小文件。
- Compaction 开销增大:文件数量增多,后台合并压力随之上升。
- Region 分裂复杂:多列族分裂策略需要额外协调。
最佳实践:通常设计 1-3 个列族,将访问频率、TTL、压缩策略相近的列归入同一列族。
设计示例
create 'user_profile',
{NAME => 'base', COMPRESSION => 'LZ4', BLOCKSIZE => '65536', TTL => 31536000},
{NAME => 'detail', COMPRESSION => 'ZSTD', BLOCKSIZE => '131072', TTL => 7776000},
{NAME => 'stat', BLOOMFILTER => 'ROW', VERSIONS => 5}
base:高频核心字段,LZ4 压缩兼顾速度与压缩比,TTL 1 年。detail:低频大字段(如详情文本),ZSTD 压缩率更高,TTL 90 天。stat:派生统计指标,保留 5 个版本以支持时序查询。
启动 HBase Shell
hbase shell
进入 Shell 后可通过 help 查看所有命令分类。
创建表
# 创建表 wzk,包含两个列族
create 'wzk', 'base_info', 'extra_info'
插入数据
put 'wzk', 'rk1', 'base_info:name', 'icu'
put 'wzk', 'rk1', 'base_info:age', 30
put 'wzk', 'rk1', 'extra_info:city', 'Beijing'
put 语法:put '表名', '行键', '列族:列名', '值'。每次 put 都会写入一个带时间戳的新版本。
查询数据
# 查询整行
get 'wzk', 'rk1'
# 查询指定列族
get 'wzk', 'rk1', 'base_info'
# 使用过滤器查询
get 'wzk', 'rk1', {FILTER => "ValueFilter(=, 'binary:icu')"}
批量扫描使用 scan:
scan 'wzk'
scan 'wzk', {STARTROW => 'rk1', STOPROW => 'rk3'}
更新数据
HBase 没有独立的 update 操作,再次 put 同一行键+列即可写入新版本,查询时默认返回最新版本:
put 'wzk', 'rk1', 'base_info:age', 31
删除数据
# 删除指定列
delete 'wzk', 'rk1', 'base_info:name'
# 删除整行
deleteall 'wzk', 'rk1'
# 删除表(需先 disable)
disable 'wzk'
drop 'wzk'
性能与维护要点
| 操作 | 建议 |
|---|---|
| 批量写入 | 使用 BufferedMutator 而非逐条 put |
| 大范围扫描 | 设置 STARTROW/STOPROW 缩小扫描范围 |
| 版本控制 | 默认保留 1 个版本,统计类列族可设置更多 |
| TTL 清理 | 为冷数据列族设置 TTL,减少存储占用 |
| BloomFilter | 随机读场景开启 ROW 级 BloomFilter,降低磁盘 IO |