做HBase开发或者运维的人,应该都有过这种经历:查资料看官方文档,满屏的英文命令看得头晕;要么就是上网搜教程,结果搜出来的文章要么太浅,只贴个命令不给解释,要么太散,东一块西一块根本串不起来。HBase的Shell命令看着简单,真正用起来却有不少讲究,比如为什么删表之前要先disable,为什么get和scan都能查数据却有这么大差别,这些细节不搞明白,写脚本或者排查问题的时候就会踩坑。
这篇博文我打算一次性把HBase Shell的常用命令讲透,从启动方式、表管理、数据读写,到运维辅助命令、实际操作演示、常见问题排查,全部串起来。同时我会把每个命令背后的设计逻辑讲清楚,比如HBase为什么需要保留多个版本的数据、filter过滤器能玩出什么花样、预分区为什么能救线上性能。不管你是刚入门HBase的开发者,还是要做日常运维的工程师,或者正在准备面试想系统梳理一遍,这篇内容都能直接拿来用。
1. HBase Shell整体思路与使用准备
1.1 Shell在HBase生态里的定位
很多人刚开始接触HBase的时候,第一反应是上手Java API,毕竟写代码才是正经开发。但实际工作中你会发现,Shell命令的使用频率一点都不比Java API低。建表、加列族、看region分布、临时查一条数据、清理垃圾数据、做快照备份,这些操作如果都要写一段Java代码去执行,效率实在太低了。
HBase Shell本质上是一个基于JRuby封装的交互式命令行工具,它把HBase的Java API包装成了一个个可以直接敲的命令。你在Shell里执行的每一条命令,底层都会转换成对应的客户端调用去访问HBase集群。所以Shell命令和Java API在功能上是对等的,区别只是使用场景不同。日常开发调试、运维管理用Shell,正式业务逻辑写入用Java API或者其他客户端,两者配合起来才是完整的HBase使用姿势。
1.2 启动Shell前的环境准备
要进入Shell,前提是HBase集群已经正常启动。这里有个容易忽略的点:HBase Shell本身不需要额外安装什么客户端,只要在一台能访问到HBase集群的机器上,把HBase的bin目录加进PATH,或者在HBase安装目录下直接执行命令就行。
# 进入HBase安装目录 cd /opt/hbase/bin # 启动Shell ./hbase shell启动之后如果能看到类似下面的输出,说明已经成功连上了集群:
HBase Shell Use "help" to get list of supported commands. Use "exit" to quit this interactive shell. For Reference, please visit: http://hbase.apache.org/2.0/book.html#shell Version 2.4.17, r2381a66c1d55b2f0e0d0c5e1b2a7e7a3f3f1d0e5, Tue Aug 9 18:41:12 PDT 2022 Took 0.0017 seconds如果你执行./hbase shell之后卡住了,或者报Can't connect to ZooKeeper之类的错误,先别急着怀疑集群挂了。多数情况下是三种原因:一是ZooKeeper的地址配置不对,检查hbase-site.xml里的hbase.zookeeper.quorum;二是本机hostname解析问题,HBase对hostname非常敏感,机器上的/etc/hosts没有配好会出现各种奇怪的连接问题;三是集群安全认证没通过,如果是开启了Kerberos的环境,需要先kinit拿到票据才能操作。
在Shell里输入status命令,能看到集群当前的运行概况,比如RegionServer有几台、每个RegionServer负载如何。集群有问题,先从这里看起。
hbase:001:0> status 1 active master, 0 backup masters, 3 servers, 0 dead, 6.0000 average load Took 0.4192 seconds看到3 servers和0 dead,说明三台RegionServer都活着,没有节点挂掉,这是最理想的状态。
2. 表管理命令:建表、查看、修改与删除的完整攻略
2.1 创建表与预分区设置
HBase建表命令是create,语法非常灵活,但也正因为灵活,新手经常会被括号里的各种花括号弄晕。我来拆开讲一下。
最简单的建表,只指定表名和一个列族:
hbase:001:0> create 'user_info', 'base'这条命令创建了一张名为user_info的表,只有一个列族base。注意,HBase建表的时候,至少要有1个列族,最多官方不建议超过5个,列族太多会严重影响性能,因为每个列族对应一个独立的存储文件(HFile),列族太多会导致写入放大的问题。
稍微复杂一点的建表,是指定列族属性:
hbase:002:0> create 'user_info', {NAME => 'base', VERSIONS => 3, TTL => 86400}这条命令里的VERSIONS => 3表示这个列族最多保留3个版本的数据,TTL => 86400表示数据存活时间是一天,过期数据会被自动清理。生产环境建表的时候,这两个参数几乎必设,不设的话默认VERSIONS是1,TTL是永久保留。VERSIONS设成1你会发现查不到历史版本,TTL不设的话数据永远不会过期,存储压力会越来越大。
再来看预分区,这个是真的能救性能的功能。HBase一张表默认只有一个region,所有写入都打到这个region上,数据量大了之后region会自动分裂,但自动分裂会有性能抖动。比较稳妥的做法是建表时直接预分区。
hbase:003:0> create 'user_log', {NAME => 'info', VERSIONS => 1}, SPLITS => ['100', '200', '300', '400']这条命令把user_log表在创建时就分成了5个region,分别对应rowkey范围:[-∞, 100)、[100, 200)、[200, 300)、[300, 400)、[400, +∞)。写入数据的时候,根据rowkey的哈希值落到不同region,就避免了单region热点问题。生产上我会用这种方式,前提是rowkey设计有规律,比如用用户ID前缀分桶。
SPLITS_FILE也是常用参数,适合region数量多、分界点多的场景:
hbase:004:0> create 'big_table', 'cf1', SPLITS_FILE => '/data/splits.txt'文件里每行一个分界点,HBase会按照文件内容自动切分region。我自己写脚本生成预分区文件时,通常是按照数字前缀或者字符串前缀均匀分布去算的,效果比手写靠谱。
2.2 查看表结构:list、describe与exists
表建完之后,怎么确认建对了?用list命令查看当前namespace下有哪些表:
hbase:005:0> list TABLE big_table user_info user_log 3 row(s)如果namespace比较多,可以指定查看某个namespace下的表:
hbase:006:0> list_namespace_tables 'default'查看表详细结构用describe,这是排查问题最常用的命令:
hbase:007:0> describe 'user_info' Table user_info is ENABLED user_info COLUMN FAMILIES DESCRIPTION {NAME => 'base', BLOOMFILTER => 'ROW', VERSIONS => '3', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => '86400 SECONDS (1 DAY)', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'} 1 row(s)describe输出里的ENABLED状态很重要。HBase表有两个状态:ENABLED和DISABLED。ENABLED状态下才能读写数据,DISABLED状态下不能读写。很多管理操作要求在DISABLED状态下才能执行,后面讲删表的时候细说。
还有一个命令是exists,用来判断某张表是否存在。我在写自动化脚本的时候经常用它做前置判断,避免重复建表报错。
hbase:008:0> exists 'user_info' Table user_info does exist Took 0.0138 seconds2.3 修改表结构:alter的进阶玩法
alter命令用来修改表结构,比如增加列族、删除列族、修改属性。最常见的需求是给表加列族:
hbase:009:0> alter 'user_info', NAME => 'address'这条命令给user_info表增加了一个名为address的列族。和关系型数据库的ALTER TABLE不同,HBase的alter操作不需要锁表,可以在线执行,所以生产环境加列族是很轻松的事情,不用停机。
修改列族属性也是一样的语法:
hbase:010:0> alter 'user_info', NAME => 'base', VERSIONS => 5把base列族的版本数从3改成5。注意,这里的修改只影响之后写入的数据,历史数据的版本还是按之前的配置保留。如果想把TTL改短,比如原来一天改成10小时:
hbase:011:0> alter 'user_info', NAME => 'base', TTL => 36000TTL的单位是秒,36000秒就是10小时。从实践角度看,线上调整TTL是解决数据膨胀最快的手段,比删数据跑Major Compaction要温和得多。
删除列族同样用alter:
hbase:012:0> alter 'user_info', 'delete' => 'address'执行这条命令要慎重,列族删了之后里面的数据全部不可恢复,而且这个操作在线上执行完之后,表的存储文件会有一个大的变动,如果表数据量很大,可能会触发比较频繁的flush和compaction。
2.4 禁用表、启用表与删除表
删表绝对是新手重灾区。很多人上手就执行:
hbase:013:0> drop 'user_info'结果报错:
ERROR: Table user_info is enabled, so cannot be dropped. Disable it first.HBase的删表流程是强制两步走:先disable再drop。原因是HBase表在ENABLED状态下,可能有客户端正在写入或读取,直接删掉会出大问题。先把表禁用,阻断所有读写请求,再执行删除,才能保证数据安全和操作一致。
hbase:014:0> disable 'user_info' hbase:015:0> drop 'user_info'disable命令执行之后,表的每个region都会经历下线流程,依次关闭,这个过程如果region数量多或者负载高,会持续几秒甚至更久。可以通过is_disabled命令确认状态:
hbase:016:0> is_disabled 'user_info' true看到true说明表已经禁用成功,可以放心drop。
需要恢复一张被禁用的表,用enable命令:
hbase:017:0> enable 'user_info'执行enable之后,表的region会重新分配上线。如果region数量特别多,enable操作也会比较慢,这是正常现象,不要中途再执行其他alter操作去抢锁。
3. 数据读写命令:put、get、scan、delete的细节与技巧
3.1 写入数据:put命令的参数拆解
HBase写数据用put,一条put命令可以写入一个单元格的数据:
hbase:018:0> put 'user_info', 'rowkey_001', 'base:name', '张三'这条命令的含义是:向user_info表写入一行,rowkey是rowkey_001,列族base下的列name的值为张三。注意列名的写法是列族:列名,冒号是必须的,没有冒号就就不是一个合法的列。
put命令还支持一次写多列:
hbase:019:0> put 'user_info', 'rowkey_001', 'base:age', '28' hbase:020:0> put 'user_info', 'rowkey_001', 'base:phone', '13800138000'执行完这三条,rowkey_001这一行就有了三个单元格。注意同一个rowkey的三次put,实际上是三次独立的写入操作,每次都会产生一个新的数据版本。
如果你希望一次put操作写入多个列,可以用Map方式:
hbase:021:0> put 'user_info', 'rowkey_002', { 'base:name' => '李四', 'base:age' => '32' }put命令还可以指定时间戳:
hbase:022:0> put 'user_info', 'rowkey_001', 'base:age', '29', 1700000000000最后一个参数是时间戳,单位是毫秒。生产环境我几乎不会手动指定时间戳,因为HBase默认会用客户端机器当前时间作为版本号,手动指定容易搞乱数据版本,只有做数据修复的时候才会用到。
3.2 查询单行:get命令的完整参数
查询单行数据用get。最简单的获取整行:
hbase:023:0> get 'user_info', 'rowkey_001' COLUMN CELL base:age timestamp=2023-11-20T10:30:00.123, value=28 base:name timestamp=2023-11-20T10:29:59.456, value=张三 base:phone timestamp=2023-11-20T10:30:00.789, value=13800138000 3 row(s)只查某一列:
hbase:024:0> get 'user_info', 'rowkey_001', {COLUMN => 'base:name'}查多个列:
hbase:025:0> get 'user_info', 'rowkey_001', {COLUMN => ['base:name', 'base:age']}查指定版本数,也就是把历史版本拉出来:
hbase:026:0> get 'user_info', 'rowkey_001', {COLUMN => 'base:age', VERSIONS => 5}这里能看到HBase的多版本特性。前提是建表时VERSIONS设置大于1,如果建表时VERSIONS是1,那这里就算指定VERSIONS => 5也查不到多个版本,因为写入时旧版本已经被覆盖了。
还可以指定时间范围查询:
hbase:027:0> get 'user_info', 'rowkey_001', {TIMERANGE => [1690000000000, 1700000000000]}TIMERANGE是一个左闭右开的区间,即[start, stop),查询这个时间范围内的版本数据。
3.3 批量扫描:scan命令与过滤器
scan是HBase最强大的查询命令。它是全表扫描,所以性能上要小心使用,生产环境没有加过滤条件的全表scan很容易把RegionServer拖垮。
最简单的scan是扫全表:
hbase:028:0> scan 'user_info'数据量小的时候没问题,数据量大就要加限制了。先用LIMIT限制返回条数:
hbase:029:0> scan 'user_info', {LIMIT => 10}指定列族扫描:
hbase:030:0> scan 'user_info', {COLUMN => 'base'}指定rowkey范围扫描。这个是最常用的操作,因为HBase的rowkey是有序存储的,范围扫描效率很高:
hbase:031:0> scan 'user_info', {STARTROW => 'rowkey_001', ENDROW => 'rowkey_010'}注意STARTROW是包含的,ENDROW是不包含的。也就是结果包含rowkey_001,但不包含rowkey_010。如果想包含rowkey_010,可以写成:
hbase:032:0> scan 'user_info', {STARTROW => 'rowkey_001', ENDROW => 'rowkey_010\x00'}这里的\x00是一个比任何字符都小的终止符,算是HBase Shell里的一个小技巧。
scan配合过滤器才是完全体。HBase Shell里最常用的是ValueFilter和RowFilter。比如过滤出name等于"张三"的行:
hbase:033:0> scan 'user_info', {FILTER => "ValueFilter(=, 'binary:张三')"}过滤出age大于30的行:
hbase:034:0> scan 'user_info', {FILTER => "ValueFilter(>=, 'binary:30')"}RowFilter配合正则表达式使用,比如查询rowkey前缀为user_的行:
hbase:035:0> scan 'user_info', {FILTER => "RowFilter(=, 'substring:user_')"}substring:是HBase过滤器内置的比较器,专门用来做包含匹配。还有PrefixFilter,也可以实现前缀过滤:
hbase:036:0> scan 'user_info', {FILTER => "PrefixFilter('user_')"}从性能角度看,PrefixFilter底层会利用rowkey有序性跳过不匹配的region,比ValueFilter效率高很多,能用PrefixFilter就用PrefixFilter。
3.4 删除数据:delete、deleteall与清空表
删除数据有delete和deleteall两个命令。delete删除一个单元格的指定版本:
hbase:037:0> delete 'user_info', 'rowkey_001', 'base:age'这条命令删除rowkey_001这一行的base:age列。默认删除最新版本,如果指定了时间戳,就删除那个时间戳对应的版本:
hbase:038:0> delete 'user_info', 'rowkey_001', 'base:age', 1700000000000deleteall删除整行:
hbase:039:0> deleteall 'user_info', 'rowkey_001'执行删除之后,数据并不会立刻从磁盘上消失,而是打上删除标记(Tombstone),后续Major Compaction的时候才会真正物理删除。这个特性解释了为什么HBase的删除操作很快,但磁盘空间没有立刻返还。
要清空表,最稳妥的方式是先disable,再drop,再create:
hbase:040:0> disable 'user_info' hbase:041:0> drop 'user_info' hbase:042:0> create 'user_info', 'base'还有一个truncate命令:
hbase:043:0> truncate 'user_info'truncate的内部实现其实就是:disable → drop → create。执行之后表结构还在,但数据全没了。在Shell里执行truncate会提示你确认,非常贴心。
4. 运维辅助命令:状态查看、快照备份与Region管理
4.1 集群状态与表状态监控
日常运维里最先用的命令就是status。它能展示集群的整体健康度:
hbase:044:0> status 'detailed'加上detailed参数,能看到每个RegionServer上分配了哪些region,每台机器的负载情况,甚至能精确到region的状态是OPEN还是CLOSING。
查看namespace列表和表列表:
hbase:045:0> list_namespace NAMESPACE default hbase 2 row(s)查看某张表被分配在哪些RegionServer上:
hbase:046:0> locate_region 'user_info', 'rowkey_001'这个命令会告诉你rowkey_001这个rowkey落在哪个region,以及这个region在哪个RegionServer上。排查数据热点、确认请求分发情况的时候非常有用。
4.2 快照备份与恢复
HBase快照是线上备份的利器。它的原理是记录表的元数据信息和HFile的文件引用信息,创建快照本身几乎不复制数据,所以非常快,对线上影响极小。
创建快照:
hbase:047:0> snapshot 'user_info', 'snap_user_info_20231120'查看快照列表:
hbase:048:0> list_snapshots SNAPSHOT TABLE + CREATION TIME snap_user_info_20231120 user_info (2023-11-20 10:00:00) 1 row(s)从快照恢复新表:
hbase:049:0> clone_snapshot 'snap_user_info_20231120', 'user_info_restore'clone_snapshot会基于快照数据创建一张新表。恢复完成后,这张表和快照时点的数据完全一致。生产环境做数据误删恢复、把线上表克隆到测试环境,用的都是这套方案。
删除不再需要的快照:
hbase:050:0> delete_snapshot 'snap_user_info_20231120'还有一个restore_snapshot命令,可以把表恢复成快照时的状态。先禁用表再restore:
hbase:051:0> disable 'user_info' hbase:052:0> restore_snapshot 'snap_user_info_20231120' hbase:053:0> enable 'user_info'restore_snapshot会覆盖当前表的数据,危险程度极高,操作前一定三思,建议在生产环境外先做演练。
4.3 Region管理与手动拆分合并
HBase的region管理一般交给系统自动完成,但某些场景需要人工介入。比如发现某个region数据量特别大,成为热点,可以手动拆分:
hbase:054:0> split 'user_info', 'rowkey_100'这里rowkey_100是拆分点,这条命令把包含rowkey_100的region从rowkey_100处一分为二。
手动合并region更谨慎,因为合并操作影响面大:
hbase:055:0> merge_region 'c9b9d1a2b4d6c7e8a0f9d8e7c6b5a4f3', 'c9b9d1a2b4d6c7e8a0f9d8e7c6b5a4f4'merge_region需要传入两个region的编码ID,可以从status 'detailed'里查到对应的region名称。没有十足把握,不建议在生产环境手动合并。
4.4 其他高频辅助命令
查看当前Shell用户是谁:
hbase:056:0> whoami查看表是否启用、是否可写:
hbase:057:0> is_enabled 'user_info'查看HBase版本信息:
hbase:058:0> version统计表行数(生产环境慎用,会触发全表扫描):
hbase:059:0> count 'user_info'count命令可以加INTERVAL参数,设置每扫描多少行打印一次进度,还可以加CACHE参数控制每次扫描缓存的行数:
hbase:060:0> count 'user_info', INTERVAL => 1000, CACHE => 10005. 实操演练:从建表到过滤查询的完整案例
5.1 场景定义与建表设计
下面用一个实际场景把前面讲的命令串起来。假设我们需要一张用户行为日志表,记录用户对推荐内容的点击行为,需要支持按用户维度的查询。
表名reco_click_log,rowkey设计为用户ID_时间戳反转。时间戳反转的意思是将Long.MaxValue减去当前时间戳,这样同一用户的最新数据会排在前面,适合"查最近点击记录"这类场景。列族设计为click,列包括item_id(内容ID)、scene(推荐场景)、cost(点击花费)。
hbase:061:0> create 'reco_click_log', {NAME => 'click', VERSIONS => 1, BLOCKCACHE => true}, SPLITS => ['100', '200', '300']这里设置了VERSIONS为1,因为点击行为的历史版本没有意义,保留最新一条就行。SPLITS设置4个分区,分别存储不同用户ID前缀的数据。
5.2 写入数据与验证
模拟写入几条数据:
hbase:062:0> put 'reco_click_log', '10001_9223372036854770000', 'click:item_id', 'A001' hbase:063:0> put 'reco_click_log', '10001_9223372036854770000', 'click:scene', 'homepage' hbase:064:0> put 'reco_click_log', '10001_9223372036854770000', 'click:cost', '10' hbase:065:0> put 'reco_click_log', '20001_9223372036854770000', 'click:item_id', 'B002' hbase:066:0> put 'reco_click_log', '20001_9223372036854770000', 'click:scene', 'detail' hbase:067:0> put 'reco_click_log', '20001_9223372036854770000', 'click:cost', '20'验证写入:
hbase:068:0> get 'reco_click_log', '10001_9223372036854770000' COLUMN CELL click:cost timestamp=2023-11-20T11:00:00.123, value=10 click:item_id timestamp=2023-11-20T11:00:00.000, value=A001 click:scene timestamp=2023-11-20T11:00:00.045, value=homepage 3 row(s)5.3 组合过滤查询演示
查用户ID前缀为10001的最近点击记录:
hbase:069:0> scan 'reco_click_log', {FILTER => "PrefixFilter('10001_')"}结果:
ROW COLUMN+CELL 10001_9223372036854770000 column=click:cost, timestamp=..., value=10 10001_9223372036854770000 column=click:item_id, timestamp=..., value=A001 10001_9223372036854770000 column=click:scene, timestamp=..., value=homepage 1 row(s)查点击花费大于等于15的记录:
hbase:070:0> scan 'reco_click_log', {FILTER => "ValueFilter(>=, 'binary:15')"}执行结果会返回20001_9223372036854770000这行的数据。注意这个过滤是在服务端做的,但binary:15是字符串比较,如果需要数值比较,需要根据实际存储的数据格式去处理,这是HBase过滤器比较隐晦的点。
如果需要多个条件组合过滤,用AND连接:
hbase:071:0> scan 'reco_click_log', {FILTER => "PrefixFilter('20001_') AND ValueFilter(>=, 'binary:15')"}这条命令先按rowkey前缀过滤,再按value过滤,两个条件同时满足才会返回结果。
5.4 快照备份的完整操作
模拟线上备份流程。先创建快照:
hbase:072:0> snapshot 'reco_click_log', 'snap_reco_click_log_0320'从快照克隆一个测试表:
hbase:073:0> clone_snapshot 'snap_reco_click_log_0320', 'reco_click_log_test'扫描测试表确认数据正常:
hbase:074:0> scan 'reco_click_log_test', {LIMIT => 5}测试完成后,删除测试表:
hbase:075:0> disable 'reco_click_log_test' hbase:076:0> drop 'reco_click_log_test'这套流程就是我平时做数据迁移、测试环境准备的标准动作。省去了用export/import导数据的时间,尤其适合大表场景。
6. 常见问题与排查技巧实录
6.1 Shell命令卡住或连接超时
典型的报错是:
ERROR: Can't get master address from ZooKeeper; znode data is null排查思路是按顺序检查:ZooKeeper服务是否正常、HBase Master进程是否存活、hbase-site.xml里的hbase.zookeeper.quorum是否配置正确、机器之间网络是否通。我碰到过最坑的一次,是某台机器的时间不同步导致和集群的session频繁超时,同步时间之后立刻恢复。
6.2 删除表卡在DISABLED状态
有时候执行disable之后,表状态一直是DISABLING,迟迟变不成DISABLED。这种情况通常是某些region的关闭流程卡住了。用status 'detailed'定位卡住的region,看看它所在的RegionServer日志有没有异常。一个快速恢复的办法是重启对应的RegionServer,让region重新调度上线后再执行disable。
6.3 scan全表导致RegionServer负载飙升
这是最危险的误操作。线上生产表动辄几十GB甚至几TB,一条scan 'big_table'不带LIMIT,可能会把集群CPU和内存打满。解决办法是:第一,日常查询务必带STARTROW和ENDROW;第二,非要过滤就用PrefixFilter这种高效的过滤器;第三,如果只是看数据结构,用LIMIT => 1先探路。
6.4 获取的数据版本和预期不一致
get命令查出来的数据版本比预期少,先检查建表时VERSIONS的设置。如果建表时设了VERSIONS为1,那写入两次同名数据后,只能查到最新一条。如果需要保留历史版本,必须先alter修改VERSIONS,再执行put。这里有一个很容易踩的坑:对已有数据执行alter修改VERSIONS之后,已经被覆盖的旧版本数据并不会恢复,只影响后续新写入的数据。
6.5 常用命令速查表
我把自己日常用的最多的命令整理成了一个速查表,方便直接复制:
| 操作类型 | 命令示例 | 说明 |
|---|---|---|
| 启动Shell | ./hbase shell | 进入HBase命令行 |
| 查看状态 | status/status 'detailed' | 查看集群和region状态 |
| 建表 | create 't1', 'cf1' | 创建单列族表 |
| 建表(预分区) | create 't1', 'cf1', SPLITS => ['10','20'] | 按分界点预分区 |
| 查看表结构 | describe 't1' | 显示列族和属性 |
| 写数据 | put 't1', 'r1', 'cf1:c1', 'v1' | 写入单单元格 |
| 查单行 | get 't1', 'r1' | 获取整行 |
| 范围扫描 | scan 't1', {STARTROW => 'r1', ENDROW => 'r2'} | 按rowkey范围扫描 |
| 条件过滤 | scan 't1', {FILTER => "PrefixFilter('r1')"} | 按前缀过滤 |
| 删除列 | delete 't1', 'r1', 'cf1:c1' | 删除单元格 |
| 删除行 | deleteall 't1', 'r1' | 删除整行 |
| 禁用表 | disable 't1' | 删除表前的必要步骤 |
| 启用表 | enable 't1' | 恢复表读写 |
| 删除表 | drop 't1' | 删除表 |
| 清空表 | truncate 't1' | 清空数据保留表结构 |
| 修改表 | alter 't1', NAME => 'cf2', VERSIONS => 3 | 修改列族属性 |
| 快照备份 | snapshot 't1', 'snap1' | 创建快照 |
| 恢复快照 | restore_snapshot 'snap1' | 恢复表到快照状态 |
| 克隆快照 | clone_snapshot 'snap1', 't2' | 从快照生成新表 |
最后再分享一个我自己的使用习惯。不要只在出问题的时候才打开Shell,平时可以在Shell里写一些简单的脚本,比如把status和disk_space的执行结果定期打出来,作为日常巡检的一部分。HBase Shell是能直接执行脚本文件的,你写好的命令集合可以存成.hb后缀的文件,以后一行命令就能自动跑完一套巡检流程。HBase的Shell命令看似零散,但只要理解了表管理、数据读写、运维操作这条主线,再用快照和预分区这两个关键功能把实际场景串起来,用起来就会非常顺手。