热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Hbase如何批量删除指定数据

一、背景:Hbase是一个列式存储,nosql类型的数据库,类似mongodb。我们都知道Hbase是一个Nosql的分布式存储数据引擎,

一、背景:

  Hbase是一个列式存储,nosql类型的数据库,类似mongodb。

        我们都知道Hbase是一个Nosql的分布式存储数据引擎,它可以支持千万级别的QPS写入,但是有时候我们需要批量的删除他的数据, 目前似乎没有提供批量删除的方法,只有一个单行删除的命令:deleteall 'tablename', rowkey

二、删除方法:

  方法一:通过写 shell 脚本,从 hbase shell 查出需要删除的 rowkey ,拼成删除命令(deleteall 'tablename', rowkey),写到文本 del_temp.txt ;然后执行 hbase shell del_temp.txt 

  方法二:通过建映射表,比如在 hive 建一个映射表,然后写 hql 查出需要删除的 rowkey ,拼成删除命令(deleteall 'tablename', rowkey),写到文本 del_temp.txt ;然后执行 hbase shell del_temp.txt 

  方法三:通过python/ java 代码,调用 hbase 的单行删除方法,写个循环删除 

  方法四:通过建映射表,比如在 hive 建一个映射表,将 需要保留的数据 通过 hql 查询出来,备份到 hive 的一张临时表 ;然后 在hbase shell 里面 执行 truncate 'tablename' ,清空 hbase 的数据; 最后 在将数据 从 hive 的备份表 读出来,插入 映射表,写回 hbase;

  总结:

  前面3种方法,本质上都是在 hbase 中逐行删除;而第4种方法,是利用hive的map reduce倒数据。对于不熟悉 hbase 和 java 语法的开发人员而言,使用2/4方法,是灵活性最好的。


第二种删除方法为例:

  1、hive 建映射表:

CREATE EXTERNAL TABLE edw.test_turboway_hbase(`keyid` string COMMENT 'from deserializer',`title` string COMMENT 'from deserializer',`bizdate` string COMMENT 'from deserializer',`loginid` string COMMENT 'from deserializer')
ROW FORMAT SERDE'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ('hbase.columns.mapping'=':key,cf:title,cf:bizdate,cf:loginid','serialization.format'='1')
TBLPROPERTIES ('COLUMN_STATS_ACCURATE'='false','hbase.table.name'='test_turboway','numFiles'='0','numRows'='-1','rawDataSize'='-1','totalSize'='0','transient_lastDdlTime'='1543297130')

  2、记录hive查询要删除的数据,拼成命令:

hive -e
"select concat('deleteall \'test_turboway\',\'',keyid,'\'')
from edw.test_turboway_hbase
where loginid = '20181122'"> del_temp.txt && echo 'exit' >> del_temp.txt

  3、hbase shell 执行删除命令

hbase shell del_temp.txt > del.log

二、

   由于从kafka消费过来写入hbase的数据量有点大,导致关联的外部hive表使用性能有点差,因此决定把已经导入hive的dwd层后的数据进行删除,删除脚本如下:

del_date=$1
filename=$(pwd)/rowkey.csvbeeline  
--incremental=true
--showHeader=false
--outputformat=dsv
--delimiterForDSV=$'\t'  
-e
"select  concat('deleteall \'default:monitorData\',\'',row_key,'\'')  
from  dw_ods.ods_api_msp_plan_point
where row_key like '%${del_date}'
">${filename}sed -i '$d' ${filename}
hbase shell ${filename} > del.log


        以上脚本删除的逻辑是首先通过外部关联表查询出需要删除的rowkey,由于这个表的rowkey后缀是日期,因此通过模糊日期查询出需要删除的rowkey写入一个文件,由于写入文件后最后一行是无关的信息,因此这里需要用sed命令进行删除。

79ba3df3493780ee65c5dcddf91b84fd.png

        脚本编辑好后,写入del_hbase.sh文件,最后执行sh del_hbase.sh yyyyMMdd进行删除指定日期的数据 


三、方法三:比如我们要删除10号到13号的数据

我们可以利用Hbase的API先scan一定时间戳范围内的数据,然后在批量的删除,具体实现的代码如下:

/*** 根据时间戳范围删除hbase的数据;*/
object HbaseUtil {def main(args: Array[String]): Unit = {val s = System.currentTimeMillis()val conf = HBaseConfiguration.create()conf.set("hbase.zookeeper.quorum", PropertiesScalaUtils.loadProperties("zk_hbase")) //zk的地址;conf.set("hbase.zookeeper.property.clientPort", PropertiesScalaUtils.loadProperties("zk_port"))conf.set("hbase.master", PropertiesScalaUtils.loadProperties("hbase_master"))conf.set("hbase.defaults.for.version.skip", "true")conf.set("hhbase.rootdir", PropertiesScalaUtils.loadProperties("hbase_rootdir"))conf.set("zookeeper.znode.parent", PropertiesScalaUtils.loadProperties("zookeeper_znode_parent"))val connection = ConnectionFactory.createConnection(conf)val table = connection.getTable(TableName.valueOf(PropertiesScalaUtils.loadProperties("hbase_table")))val scan = new Scan()scan.setTimeRange(args(0).toLong,args(1).toLong)val rs = table.getScanner(scan)val it = rs.iterator()val list = new util.ArrayList[Delete]()while (it.hasNext){val delete = it.next()val d = new Delete(delete.getRow)list.add(d)}if(list.size()>0){println("一共有多少条数据:"+list.size())println("开始删除--------------------")table.delete(list)println("删除完成--------------------")}else{println("没有数据--------------------")}table.close()connection.close()val e = System.currentTimeMillis()println("总共用时:"+ (e-s) +"毫秒")}
}

这么写虽然能实现对指定时间戳范围内的数据进行删除,但是这么写就没有问题吗,是有问题的,这样删除的效率是非常低的,因为需要先把需要删除的查出来放到一个list里面,然后在进行批量的删除,这个方法对于数据量小的时候是可以的,数据量大的话,就会非常的慢,一定要根据自己的实际情况而定

这两种方法还是推荐使用第一张设置TTL,让其自动过期,如果非要删除段时间范围内的,可以用第二种但是要考虑性能问题.
————————————————
 


推荐阅读
author-avatar
Libra
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有