HBase扫描数据 #
一、SCAN语法 #
1.1 基本语法 #
ruby
# 基本语法
scan '表名'
# 示例
scan 'user'
1.2 完整语法 #
ruby
# 完整语法
scan '表名', {选项}
# 示例
scan 'user', {STARTROW => 'user001', STOPROW => 'user010', LIMIT => 10}
二、基本扫描操作 #
2.1 全表扫描 #
ruby
# 全表扫描
scan 'user'
# 输出示例
ROW COLUMN+CELL
user001 column=info:age, timestamp=1704067200000, value=25
user001 column=info:name, timestamp=1704067200000, value=张三
user002 column=info:age, timestamp=1704067200000, value=30
user002 column=info:name, timestamp=1704067200000, value=李四
2.2 扫描指定列族 #
ruby
# 扫描指定列族
scan 'user', {COLUMN => 'info'}
# 输出示例
ROW COLUMN+CELL
user001 column=info:age, timestamp=1704067200000, value=25
user001 column=info:name, timestamp=1704067200000, value=张三
2.3 扫描指定列 #
ruby
# 扫描指定列
scan 'user', {COLUMN => 'info:name'}
# 扫描多列
scan 'user', {COLUMN => ['info:name', 'info:age']}
2.4 扫描命名空间中的表 #
ruby
# 扫描命名空间中的表
scan 'myapp:user'
三、范围查询 #
3.1 指定行范围 #
ruby
# 指定起始行
scan 'user', {STARTROW => 'user001'}
# 指定结束行
scan 'user', {STOPROW => 'user010'}
# 指定范围
scan 'user', {STARTROW => 'user001', STOPROW => 'user010'}
# 注意:STARTROW包含,STOPROW不包含
# [user001, user010)
3.2 行范围示例 #
ruby
# 数据
# user001, user002, user003, user010, user011, user020
# 查询 user001 到 user010 之间的数据
scan 'user', {STARTROW => 'user001', STOPROW => 'user010'}
# 返回:user001, user002, user003
# 不包含 user010
# 查询 user010 到 user020 之间的数据
scan 'user', {STARTROW => 'user010', STOPROW => 'user020'}
# 返回:user010, user011
# 不包含 user020
3.3 反向扫描 #
ruby
# 反向扫描
scan 'user', {STARTROW => 'user010', STOPROW => 'user001', REVERSED => true}
# 注意:反向扫描时,STARTROW > STOPROW
3.4 前缀扫描 #
ruby
# 扫描特定前缀的行
scan 'user', {STARTROW => 'user001', STOPROW => 'user002'}
# 使用RowFilter进行前缀过滤
scan 'user', {FILTER => "PrefixFilter('user00')"}
四、限制结果 #
4.1 限制返回行数 #
ruby
# 限制返回行数
scan 'user', {LIMIT => 10}
4.2 限制返回版本 #
ruby
# 限制返回版本数
scan 'user', {VERSIONS => 3}
4.3 限制返回列数 #
ruby
# 每行返回的列数限制
scan 'user', {COLUMN => 'info', LIMIT => 10}
五、时间范围查询 #
5.1 指定时间戳 #
ruby
# 查询指定时间戳的数据
scan 'user', {TIMESTAMP => 1704067200000}
5.2 指定时间范围 #
ruby
# 查询时间范围内的数据
scan 'user', {TIMERANGE => [1704067200000, 1704067300000]}
# 注意:时间范围 [start, end),start包含,end不包含
5.3 时间范围示例 #
ruby
# 查询最近1小时的数据
now = Time.now.to_i * 1000
one_hour_ago = now - 3600000
scan 'user', {TIMERANGE => [one_hour_ago, now]}
六、过滤器 #
6.1 过滤器语法 #
ruby
# 过滤器语法
scan '表名', {FILTER => "过滤器类型(比较器)"}
6.2 常用过滤器 #
RowFilter(行键过滤器) #
ruby
# 行键等于
scan 'user', {FILTER => "RowFilter(=, 'binary:user001')"}
# 行键前缀
scan 'user', {FILTER => "RowFilter(=, 'binaryprefix:user00')"}
# 行键正则
scan 'user', {FILTER => "RowFilter(=, 'regexstring:user00.*')"}
PrefixFilter(前缀过滤器) #
ruby
# 前缀过滤
scan 'user', {FILTER => "PrefixFilter('user00')"}
ValueFilter(值过滤器) #
ruby
# 值等于
scan 'user', {FILTER => "ValueFilter(=, 'binary:张三')"}
# 值前缀
scan 'user', {FILTER => "ValueFilter(=, 'binaryprefix:张')"}
# 值正则
scan 'user', {FILTER => "ValueFilter(=, 'regexstring:张.*')"}
QualifierFilter(列限定符过滤器) #
ruby
# 列名等于
scan 'user', {FILTER => "QualifierFilter(=, 'binary:name')"}
# 列名前缀
scan 'user', {FILTER => "QualifierFilter(=, 'binaryprefix:na')"}
FamilyFilter(列族过滤器) #
ruby
# 列族等于
scan 'user', {FILTER => "FamilyFilter(=, 'binary:info')"}
SingleColumnValueFilter(单列值过滤器) #
ruby
# 单列值过滤
scan 'user', {FILTER => "SingleColumnValueFilter('info', 'age', =, 'binary:25')"}
# 过滤不匹配的行
scan 'user', {FILTER => "SingleColumnValueFilter('info', 'age', >, 'binary:20')"}
# 如果列不存在也返回
scan 'user', {FILTER => "SingleColumnValueFilter('info', 'age', >=, 'binary:20', true, true)"}
ColumnPrefixFilter(列前缀过滤器) #
ruby
# 列前缀过滤
scan 'user', {FILTER => "ColumnPrefixFilter('na')"}
MultipleColumnPrefixFilter(多列前缀过滤器) #
ruby
# 多列前缀过滤
scan 'user', {FILTER => "MultipleColumnPrefixFilter('na', 'ag')"}
PageFilter(分页过滤器) #
ruby
# 分页查询
scan 'user', {FILTER => "PageFilter(10)"}
6.3 过滤器组合 #
ruby
# AND组合
scan 'user', {FILTER => "RowFilter(=, 'binaryprefix:user00') AND ValueFilter(=, 'binary:张三')"}
# OR组合
scan 'user', {FILTER => "ValueFilter(=, 'binary:张三') OR ValueFilter(=, 'binary:李四')"}
# NOT组合
scan 'user', {FILTER => "NOT ValueFilter(=, 'binary:张三')"}
# 复杂组合
scan 'user', {FILTER => "(RowFilter(=, 'binaryprefix:user00') AND ValueFilter(=, 'binary:张三')) OR ValueFilter(=, 'binary:李四')"}
6.4 比较器 #
| 比较器 | 说明 | 示例 |
|---|---|---|
| binary | 二进制比较 | ‘binary:value’ |
| binaryprefix | 二进制前缀比较 | ‘binaryprefix:pre’ |
| regexstring | 正则表达式 | ‘regexstring:pattern’ |
| substring | 子字符串匹配 | ‘substring:sub’ |
6.5 比较运算符 #
| 运算符 | 说明 |
|---|---|
| = | 等于 |
| != | 不等于 |
| > | 大于 |
| >= | 大于等于 |
| < | 小于 |
| <= | 小于等于 |
七、扫描示例 #
7.1 用户信息扫描 #
ruby
# 扫描所有用户
scan 'user', {COLUMN => 'info'}
# 扫描特定用户范围
scan 'user', {STARTROW => 'user001', STOPROW => 'user010', COLUMN => 'info'}
# 扫描年龄大于20的用户
scan 'user', {FILTER => "SingleColumnValueFilter('info', 'age', >, 'binary:20')"}
# 分页扫描
scan 'user', {STARTROW => 'user001', LIMIT => 10}
7.2 订单信息扫描 #
ruby
# 扫描用户订单
scan 'order', {STARTROW => 'user001_', STOPROW => 'user001_~'}
# 扫描最近订单
scan 'order', {STARTROW => 'user001_', STOPROW => 'user001_~', LIMIT => 10}
# 扫描已支付订单
scan 'order', {FILTER => "SingleColumnValueFilter('detail', 'status', =, 'binary:paid')"}
7.3 时序数据扫描 #
ruby
# 扫描设备数据
scan 'sensor', {STARTROW => 'device001_', STOPROW => 'device001_~'}
# 扫描最近数据
scan 'sensor', {STARTROW => 'device001_', STOPROW => 'device001_~', LIMIT => 100}
# 扫描时间范围数据
scan 'sensor', {TIMERANGE => [1704067200000, 1704067300000]}
八、Java API扫描 #
8.1 基本扫描 #
java
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
public class ScanExample {
public static void main(String[] args) throws Exception {
Connection connection = ConnectionFactory.createConnection();
Table table = connection.getTable(TableName.valueOf("user"));
// 创建Scan对象
Scan scan = new Scan();
// 执行扫描
ResultScanner scanner = table.getScanner(scan);
// 遍历结果
for (Result result : scanner) {
String rowKey = Bytes.toString(result.getRow());
String name = Bytes.toString(
result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"))
);
System.out.println("RowKey: " + rowKey + ", Name: " + name);
}
scanner.close();
table.close();
connection.close();
}
}
8.2 范围扫描 #
java
// 创建Scan对象
Scan scan = new Scan();
// 设置范围
scan.setStartRow(Bytes.toBytes("user001"));
scan.setStopRow(Bytes.toBytes("user010"));
// 设置列
scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
// 执行扫描
ResultScanner scanner = table.getScanner(scan);
8.3 使用过滤器 #
java
import org.apache.hadoop.hbase.filter.*;
// 创建过滤器
Filter filter = new PrefixFilter(Bytes.toBytes("user00"));
// 设置过滤器
Scan scan = new Scan();
scan.setFilter(filter);
// 执行扫描
ResultScanner scanner = table.getScanner(scan);
8.4 分页扫描 #
java
// 分页扫描
byte[] lastRow = null;
int pageSize = 100;
while (true) {
Scan scan = new Scan();
scan.setLimit(pageSize);
if (lastRow != null) {
scan.setStartRow(lastRow);
}
ResultScanner scanner = table.getScanner(scan);
int count = 0;
for (Result result : scanner) {
// 处理结果
lastRow = result.getRow();
count++;
}
scanner.close();
if (count < pageSize) {
break; // 没有更多数据
}
}
九、性能优化 #
9.1 扫描优化建议 #
text
扫描优化建议
├── 指定列族和列
│ └── 减少数据传输
│
├── 使用范围限制
│ └── STARTROW/STOPROW
│
├── 使用过滤器
│ └── 服务端过滤减少传输
│
├── 设置缓存大小
│ └── 合理设置scanner caching
│
├── 使用分页
│ └── 避免一次扫描大量数据
│
└── 关闭BlockCache
└── 一次性扫描场景
9.2 缓存配置 #
xml
<!-- hbase-site.xml -->
<!-- Scanner缓存大小 -->
<property>
<name>hbase.client.scanner.caching</name>
<value>100</value>
</property>
<!-- Scanner超时时间 -->
<property>
<name>hbase.client.scanner.timeout.period</name>
<value>60000</value>
</property>
9.3 Java API缓存设置 #
java
// 设置Scanner缓存
Scan scan = new Scan();
scan.setCaching(100); // 每次RPC返回100行
scan.setCacheBlocks(false); // 关闭BlockCache(一次性扫描)
十、常见问题 #
10.1 扫描超时 #
ruby
# 问题:扫描大量数据超时
# 解决:设置超时时间或分页扫描
# 分页扫描
scan 'user', {LIMIT => 1000}
10.2 内存溢出 #
ruby
# 问题:扫描大量数据内存溢出
# 解决:使用分页或限制返回列
# 限制返回列
scan 'user', {COLUMN => 'info:name', LIMIT => 1000}
10.3 扫描慢 #
ruby
# 问题:扫描速度慢
# 解决:使用过滤器、范围限制
# 使用过滤器
scan 'user', {FILTER => "PrefixFilter('user00')"}
# 使用范围限制
scan 'user', {STARTROW => 'user001', STOPROW => 'user010'}
十一、最佳实践 #
11.1 扫描设计 #
text
扫描设计建议
├── 避免全表扫描
├── 使用范围限制
├── 使用过滤器
├── 指定需要的列
└── 合理设置缓存
11.2 性能优化 #
text
性能优化建议
├── 使用StartRow/StopRow
├── 使用过滤器减少传输
├── 设置合理的caching值
├── 分页处理大数据量
└── 关闭BlockCache(一次性扫描)
11.3 数据一致性 #
text
数据一致性建议
├── 理解MVCC机制
├── 注意时间范围查询
└── 关注版本数设置
十二、总结 #
本节介绍了HBase扫描数据:
| 操作 | 语法 |
|---|---|
| 全表扫描 | scan ‘表’ |
| 范围扫描 | scan ‘表’, |
| 列扫描 | scan ‘表’, |
| 过滤器 | scan ‘表’, |
| 分页 | scan ‘表’, |
| 时间范围 | scan ‘表’, |
下一步,让我们学习高级特性!
最后更新:2026-03-27