这篇文章主要介绍HBase中Scan类属性maxResultSize有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
如果你看过HRegionServer的启动过程,你会发现他也有一个类似的属性maxScannerResultSize(配置文件中通过hbase.client.scanner.max.result.size设置),其实这个值就是Scan做扫描时候maxResultSize的默认值,那这个maxResultSize到底有什么用,我们看下面的源码(摘自hbase0.98.9 HRegionServer的scan方法):
LOG.info("*******4444************maxResultSize:"+maxResultSize + ";rows:"+rows); synchronized(scanner) { while (i < rows) { // Stop collecting results if maxScannerResultSize is set and we have exceeded it if ((maxScannerResultSize < Long.MAX_VALUE) && (currentScanResultSize >= maxResultSize)) { LOG.info("*************kreak i :"+i); break; } // Collect values to be returned here boolean moreRows = scanner.nextRaw(values); if (!values.isEmpty()) { for (Cell cell : values) { KeyValue kv = KeyValueUtil.ensureKeyValue(cell); LOG.info("*************kv :"+kv +";kv.heapSize():"+kv.heapSize()); LOG.info("*************currentScanResultSize :"+currentScanResultSize); currentScanResultSize += kv.heapSize(); totalKvSize += kv.getLength(); } results.add(Result.create(values)); i++; } if (!moreRows) { break; } values.clear(); } }
大家会看到一些调试代码,也莫见怪了。
大家看“if((maxScannerResultSize < Long.MAX_VALUE) && (currentScanResultSize >= maxResultSize))” 这个条件判断语句,很重要的一个判断是currentScanResultSize >= maxResultSize,而这里的currentScanResultSize,其实是每行所有KeyValue的bytes的统计数,意思是当在Scan对象中设置了maxResultSize后(没设置的话,默认值为HRegionServer的maxScannerResultSize),在HRegionServer中扫描数据的时候,会对所查数据的bytes统计和与这个值做比较,这样的结果是如果maxResultSize比较小,那么本来需要10条数据一次能够查询到的,需要分成多次查询,其maxResultSize的值,并不会影响查询的结果,只会影响scan发起远程调用的次数,这里可能说得有点抽象,我举个例子说明:
在我的HBase数据库中存在记录:row-10,row-11,...,row-19,row-20,row-21,...,row-29,...,row-91,row-92,...,row-99
分别用两种下面三种方式查询,都能得到一样的结果:
keyvalues={row-10/colfam1:col-5/1423054405356/Put/vlen=8/mvcc=0, row-10/colfam2:col-33/1423054405467/Put/vlen=9/mvcc=0} keyvalues={row-100/colfam1:col-5/1423054437916/Put/vlen=9/mvcc=0, row-100/colfam2:col-33/1423054437979/Put/vlen=10/mvcc=0} keyvalues={row-11/colfam1:col-5/1423054405753/Put/vlen=8/mvcc=0, row-11/colfam2:col-33/1423054405869/Put/vlen=9/mvcc=0} keyvalues={row-12/colfam1:col-5/1423054406160/Put/vlen=8/mvcc=0, row-12/colfam2:col-33/1423054406268/Put/vlen=9/mvcc=0} keyvalues={row-13/colfam1:col-5/1423054406541/Put/vlen=8/mvcc=0, row-13/colfam2:col-33/1423054406646/Put/vlen=9/mvcc=0} keyvalues={row-14/colfam1:col-5/1423054406937/Put/vlen=8/mvcc=0, row-14/colfam2:col-33/1423054407028/Put/vlen=9/mvcc=0} keyvalues={row-15/colfam1:col-5/1423054407305/Put/vlen=8/mvcc=0, row-15/colfam2:col-33/1423054407424/Put/vlen=9/mvcc=0} keyvalues={row-16/colfam1:col-5/1423054407715/Put/vlen=8/mvcc=0, row-16/colfam2:col-33/1423054407813/Put/vlen=9/mvcc=0} keyvalues={row-17/colfam1:col-5/1423054408084/Put/vlen=8/mvcc=0, row-17/colfam2:col-33/1423054408198/Put/vlen=9/mvcc=0} keyvalues={row-18/colfam1:col-5/1423054408490/Put/vlen=8/mvcc=0, row-18/colfam2:col-33/1423054408598/Put/vlen=9/mvcc=0} keyvalues={row-19/colfam1:col-5/1423054408895/Put/vlen=8/mvcc=0, row-19/colfam2:col-33/1423054409007/Put/vlen=9/mvcc=0} keyvalues={row-2/colfam1:col-5/1423054402056/Put/vlen=7/mvcc=0, row-2/colfam2:col-33/1423054402181/Put/vlen=8/mvcc=0}
方法一:
Scan scan3 = new Scan(); scan3.setCaching(9); scan3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5")) .addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col-33")) .setStartRow(Bytes.toBytes("row-10")).setStopRow(Bytes.toBytes("row-20")); ResultScanner scanner3 = table.getScanner(scan3); for (Result res : scanner3) { System.err.println(res); } scanner3.close();
方法二:
Scan scan3 = new Scan(); //scan3.setCaching(9); scan3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5")) .addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col-33")) .setStartRow(Bytes.toBytes("row-10")).setStopRow(Bytes.toBytes("row-20")).setMaxResultSize(5); ResultScanner scanner3 = table.getScanner(scan3); for (Result res : scanner3) { System.err.println(res); } scanner3.close();
方法三:
Scan scan3 = new Scan(); scan3.setCaching(9); scan3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5")) .addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col-33")) .setStartRow(Bytes.toBytes("row-10")).setStopRow(Bytes.toBytes("row-20")).setMaxResultSize(5); ResultScanner scanner3 = table.getScanner(scan3); for (Result res : scanner3) { System.err.println(res); } scanner3.close();
方法一和方法二的区别,在于方法一中scan设置了caching属性为9,方法二中没设置该属性,但设置了maxResultSize属性,
方法二和方法三的区别,在于方法三在方法二的基础上设置了caching属性为9,
基于上面的例子,做以下几点说明:
1、如果不设置scan的caching属性,本例中要查询row-10到row-20的属性,需要在client发起最少11次的远程访问,从HRegionServer中获取数据,并且每次只查询一条记录。
2、对于maxResultSize,只对一次client的远程访问起作用,如果一次远程调用只取一条数据,这个值的设置没有意义;对于批量数据获取,即Scan设置caching后,这个值会起到限制作用,比如,例子中Scan设置caching为9,同时设置maxResultSize为5,并且事先可以知道每行数据的bytes是112,在这样的条件下,结合HRegionServer中scan方法中的限制代码,即使Scan设置了caching为9,一次远程调用也只能取到一条记录,原因也就是“if ((maxScannerResultSize < Long.MAX_VALUE) && (currentScanResultSize >= maxResultSize)) “ 执行这个逻辑检查的时候,被break,跳出循环了。 所以,Scan设置caching为9理想情况下,是能2次远程调用就取到12条记录,但是由于设置了maxResultSize为5,在检查每次远程调用能返回的bytes数的时候,就只能返回一条记录了。
3、方法二和方法三效果完全一样,方法一只需要client发起三次远程调用,便可取到所需数据。
4、maxResultSize的意义:限制每次client从HRegionServer取到的bytes总数,bytes总数通过row的KeyValue计算得出。
以上是“HBase中Scan类属性maxResultSize有什么用”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。