首批通过分布式安全可靠测评,为关键业务系统打造
OBKV-HBase 查询优化
更新时间:2026-07-23 19:56:22
OBKV-HBase 的查询原始实现采用全范围扫描策略,先扫描所有列限定符(Qualifier,即列名)的数据再进行过滤。这种方式在服务端会产生大量冗余扫描和处理开销,特别是当对一个宽行或者多版本的行查询只涉及少量列时,延迟问题尤为明显。
本文介绍 OBKV-HBase 的查询优化(即针对 get 操作的优化)功能,帮助您在宽行或者多版本的行查询场景下提升查询性能。
功能说明
本特性提供一个配置项,用于在执行 get 操作时启用查询优化功能。当启用时,查询会在服务端基于 OBKV-HBase 的智能扫描技术进行优化处理,快速跳过宽行或多版本的行,从而降低查询时延。
该功能主要针对宽行或热 Key(版本数量多)场景。当 HBase 宽行中不同 Qualifier(即列名)的数量加上所有 Qualifier 的版本总数超过 1000 时,优化效果会非常明显。
注意
开启该配置项后,客户端仅向服务器送优化建议。服务器会根据实际情况评估是否执行优化,因此配置项开启后,优化效果可能不会在所有场景下生效。
使用限制
该优化功能仅在满足以下所有条件时生效:
| 限制条件 | 说明 |
|---|---|
| 仅适用于 get 操作 | 不支持 scan 操作 |
| MaxVersions = 1 | 表级别设置了 MaxVersions=1,或在 get 操作中配置了 get.setMaxVersions(1) |
| 非时序表 | 不支持时序表 |
| 不指定 Filter | 查询时不能指定 Filter |
| 不支持 reverse scan | 查询时不能使用 reverse scan |
| 本地读取 | 服务端执行时需要本地读取(分布式场景下 batch get 可能会进行远程执行,此时优化不生效) |
该功能支持语句级别和全局级别两种配置方式,不同配置方式有不同的数据类型限制,具体说明如下:
- 语句级别配置:必须通过
Get.setAttribute()方法设置,参数类型为byte[]类型,直接传入字符串"true"或"false"的字节数组(如"true".getBytes())即可,服务端会自动解析为布尔值。 - 全局级别配置:必须为布尔类型或可解析为布尔值的字符串(
"true"/"false")。
性能影响说明:
- 该优化主要针对宽行或多版本场景,对于非以上场景,优化效果可能不会很明显。
配置项
该功能支持语句级别和全局级别两种配置方式:
| 配置级别 | 常量名 | 配置值 | 类型 | 默认值 |
|---|---|---|---|---|
| 语句级别 | HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE |
hbase.htable.hotkey.get.optimize.enable |
byte[](通过 Get.setAttribute() 设置) |
false |
| 全局级别 | HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE_GLOBAL |
hbase.htable.hotkey.get.optimize.enable.global |
boolean(通过 Configuration 设置) |
false |
优先级规则:
- 语句级别优先:如果通过
Get.setAttribute()设置了语句级别的配置,则使用该配置值。 - 全局配置作为后备:如果语句级别未配置,则使用全局配置。
- 默认值:如果两个级别都未配置,默认值为
false。
使用方法
通过 Get.setAttribute() 方法为单个 get 操作设置优化开关,适用于需要细粒度控制的场景。
单个 get 操作示例:
Get get = new Get(Bytes.toBytes("rowkey"));
get.addColumn(family.getBytes(), column.getBytes());
// 启用热键 Get 优化
get.setAttribute(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE, "true".getBytes());
// 或者禁用
// get.setAttribute(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE, "false".getBytes());
Result result = hTable.get(get);
批量 get 操作示例:
List<Get> gets = new ArrayList<>();
for (String key : keys) {
Get get = new Get(Bytes.toBytes(key));
get.addColumn(family.getBytes(), column.getBytes());
get.setAttribute(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE, "true".getBytes());
gets.add(get);
}
Result[] results = hTable.get(gets);
通过 Configuration 对象设置全局优化开关,适用于需要统一控制的场景。
Configuration configuration = ObHTableTestUtil.newConfiguration();
// 全局启用 get 查询优化
configuration.setBoolean(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE_GLOBAL, true);
OHTable hTable = new OHTable(configuration, "table_name");
// 此时所有未设置语句级别配置的 get/scan 操作都会使用全局配置
Get get = new Get(Bytes.toBytes("rowkey"));
Result result = hTable.get(get); // 会自动使用全局配置的 true 值
语句级别配置可以覆盖全局配置,适用于大部分操作需要优化、少数操作需要关闭优化的场景。
Configuration configuration = ObHTableTestUtil.newConfiguration();
// 全局启用
configuration.setBoolean(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE_GLOBAL, true);
OHTable hTable = new OHTable(configuration, "table_name");
// Get1:不设置语句级别,使用全局配置(true)
Get get1 = new Get(Bytes.toBytes("rowkey1"));
Result result1 = hTable.get(get1);
// Get2:设置语句级别为 false,覆盖全局配置
Get get2 = new Get(Bytes.toBytes("rowkey2"));
get2.setAttribute(HBASE_HTABLE_HOTKEY_GET_OPTIMIZE_ENABLE, "false".getBytes());
Result result2 = hTable.get(get2); // 使用 false,而不是全局的 true