博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
记一次Hbase查询速度优化经历
阅读量:5037 次
发布时间:2019-06-12

本文共 5847 字,大约阅读时间需要 19 分钟。

项目背景

  在这次影像系统中,我们利用大数据平台做的是文件(图片、视频等)批次的增删改查,每个批次都包含多个文件,上传完成以后要添加文件索引(文件信息及批次信息),由于在Hbase存储的过程中,每个文件都对应一个文件rowKey,一个批次就会有很多个RoweKey,查询的下载的时候就必须根据每个文件的rowkey找到对应的文件,如果一个批次有很多个文件的话,就需要查找很多次,这样是很浪费时间的,一开始没注意这么多,开发并且完成功能测试后,觉得一切OK,但是作为大数据后台,对效率的要求非常高,在压力测试的时候出现了问题,并发量上来之后,查询下载的速度非常慢,TPS总上不去,仔细分析代码后,发现了问题。

改进之前的部分代码如下:

public List
batchGetFileMeta (String systemType, String batchNo, String fileName,String versionNo,BufferedOutputStream bw) { List
fileInfoList = new ArrayList
(); FileStoreInfo fileStoreInfo = batchGetFileStoreInfo(systemType,batchNo, versionNo,bw); if(fileStoreInfo == null){ return null; } List
fileNameList=batchGetFileNameByBathNO(systemType,batchNo, fileName, versionNo,bw); if(fileNameList == null || fileNameList.size()==0 ){ return null; } if(fileNameList.size()==1 && ("".equals(fileNameList.get(0)))){ fileInfoList.add(null); return fileInfoList; } int hash = batchNo.hashCode(); String rowKey = ""; String fileNName = fileStoreInfo.getFile_N_Name(); String[] fileNNameArray = fileNName.split(Constants.SPLIT); for(int i=0;i
fileInfoMaps = new HashMap
(); fileInfoMaps = HbaseUtil.queryBykey(Constants.HBASE_TAB+systemType, rowKey, Constants.HBASE_FAMILYY_CF1, Constants.HBASE_COLUMN_L); if(fileInfoMaps == null ){ return null; } String fileInfoStr = fileInfoMaps.get("value"); FileInfo fileInfo = new FileInfo(); fileInfo = (FileInfo) Utils.jsonToObj(fileInfoStr,fileInfo); if(fileInfo == null){ return null; } String userdefinede = getUserDefinedE(systemType, rowKey); fileInfo.setUserDefined(userdefinede); return fileInfo; }public Map
queryBykey(String tableName, String rowKey,String fam, String col) { Map
result = new HashMap
(); HTable table=null; try { if(isExistTable(tableName)){ table = new HTable(conf, tableName); Get scan = new Get(rowKey.getBytes()); Result r = table.get(scan); byte[] bs = r.getValue(Bytes.toBytes(fam), Bytes.toBytes(col)); String value = Bytes.toString(bs); result.put("value", value); table.close(); return result; }else{ return null; } } catch (IOException e) { e.printStackTrace(); return null; }

测试结果如下:

  虽然时间比较少,但是远远不能满足效率要求。仔细分析上面代码不难发现:由于业务需要查询数据的时候要校验文件信息,所以代码中出现了循环套循环的情况,如果某批次的文件数量特别多的话那么循环查询的次数的增长不是一个数量级的,相当大的一个数字,问题的原因在于拼接rowkey,然后拿着rowkey去查询,循环多少次就查多少次,虽然Hbase查询速度快,但这样也是在浪费时间,经过思考和研究HbaseAPI的时候发现,Hbase支持rowkey批量查询,思路大概是这样的:

1)  循环文件信息,循环之中得到拼接rowkey的信息

2)  把得到的rowkey放入list中

3)  循环完毕,用List去查Hbase,将得到的信息放入Map返回

4)  获取Map中的信息

下面是改进之后的代码:

改进后:

public List
batchGetFileMetaByBathNo(String systemType, String batchNo, String fileName,String versionNo,BufferedOutputStream bw) { List
fileInfoList = new ArrayList
(); FileStoreInfo fileStoreInfo =batchGetFileStoreInfo(systemType, batchNo, versionNo,bw); if(fileStoreInfo == null){ return null; } List
fileNameList=batchGetFileNameByBathNO(systemType, batchNo, fileName, versionNo,bw); if(fileNameList == null || fileNameList.size()==0 ){ return null; } if(fileNameList.size()==1 && ("".equals(fileNameList.get(0)))){ fileInfoList.add(null); return fileInfoList; } String rowKey = ""; List
rowkeylist=new ArrayList<>(); String fileNName = fileStoreInfo.getFile_N_Name(); String[] fileNNameArray = fileNName.split(Constants.SPLIT); for(int i=0;i
batchGetFileMetaByIndex(String systemType, List
rowKey, BufferedOutputStream bw) { List
fileInfoList=new ArrayList<>(); List
>list=HbaseUtil.queryByList(Constants.HBASE_TAB+systemType, rowKey); if(list.size()==0){ return null; } for(Map
resultMap:list){ FileInfo fileInfo = new FileInfo(); String LValue = resultMap.get(Constants.HBASE_COLUMN_L); String EValue=resultMap.get(Constants.HBASE_COLUMN_E); if(!"".equals(LValue)&&null!=LValue){ fileInfo = (FileInfo) Utils.jsonToObj(LValue,fileInfo); } if(!"".equals(EValue)&&null!=EValue&&fileInfo!=null){ fileInfo.setUserDefined(EValue); } fileInfoList.add(fileInfo); } return fileInfoList; }public List
> queryByList(String tableName,List
rowKeyList){ Connection connection=null; List
> list=new ArrayList<>(); List
getList=new ArrayList
(); try { connection=ConnectionFactory.createConnection(conf); Table table=connection.getTable(TableName.valueOf(tableName)); for(String rowKey:rowKeyList){ Get get=new Get(Bytes.toBytes(rowKey)); get.addFamily(Bytes.toBytes(Constants.HBASE_FAMILYY_CF1)); getList.add(get); } Result[]results=table.get(getList); for (Result result:results) { Map
listMap=new HashMap<>(); for(Cell kv:result.rawCells()){ if(Bytes.toString(kv.getQualifier()).equals(Constants.HBASE_COLUMN_E)){ listMap.put(Constants.HBASE_COLUMN_E, Bytes.toString(CellUtil.cloneValue(kv))); }else{ listMap.put(Constants.HBASE_COLUMN_L, Bytes.toString(CellUtil.cloneValue(kv))); } } list.add(listMap); } } catch (IOException e) { e.fillInStackTrace(); }finally{ try { if(connection!=null&&!connection.isClosed()){ connection.close(); } } catch (IOException e) { e.fillInStackTrace(); } } return list; }

  Hbase是支持批量查询的,经过改进之后,从代码中就可以看出,效率提升了很多,我们对10000条数据进行了测试,发现提升的效率非常明显,下面是测试图:

  进过优化后,从时间上,我们可以看到,提升的效率非常明显,这就告诉我们在做项目写代码的时候,不要只局限于功能的实现,还要考虑效率上的可行性,从一开始就要做好铺垫,否则到后期再改是非常麻烦的。

转载于:https://www.cnblogs.com/10158wsj/p/8214583.html

你可能感兴趣的文章
IE9下解决disable不能脱离焦点问题
查看>>
Android开发学习必备的java知识
查看>>
2017-2018-1 20155330 《信息安全系统设计基础》第4周学习总结
查看>>
第8次作业
查看>>
(转)Nginx在RedHat中系统服务配置脚本
查看>>
Palindromes
查看>>
SVN图形客户端上传静态库.a文件失败
查看>>
[HTML5] Show Different Variations of Images Depending on the Viewport Width using Art Direction
查看>>
[AngularJS + Unit Testing] Testing a component with requiring ngModel
查看>>
[Algorithm] Reverse array of Chars by word
查看>>
[TypeScript] Create random integers in a given range
查看>>
tampermonkey,采用js解析自定义脚本,实现网页列表数据采集分析
查看>>
Linux Kernel 整数溢出漏洞
查看>>
hdu 4001 To Miss Our Children Time
查看>>
jmeter+ant+jenkins 框架搭建(二)
查看>>
多播委托与观察者模式联合使用,以及委托与事件的区别
查看>>
批量get_flag v3
查看>>
[ubuntu]一文解决ubuntu换源相关的所有问题
查看>>
封装与解封装
查看>>
最长英语单词链
查看>>