Hbase数据库比拟实用于写多读少的场景。其查问能力并不突出。
在应用Scan扫描表的时候,很容易踩坑。

踩坑1:在表数据量偏大的状况下(比方上千万数据),执行scan提醒60000ms的timeout,并且呈现OOM。
剖析:

scan对象有几个重要的参数:  caching:该值示意一次从RPC申请Client能够从Hbase服务器获取的数据条数。           默认值是-1。依照源码,如果是-1,那么发送给Hbase的值是:HConstants#DEFAULT_HBASE_CLIENT_SCANNER_CACHING,即:           Integer.MAX_VALUE。 这是一个十分大的值。           ![image.png](/img/bVcRFNj)  maxResultSize:client从Hbase服务端获取的数据在客户端缓存的最大字节数。                 默认是-1。如果应用的是默认值,则缓存大小限度是:2M(即 2 * 1024 * 1024)。                    ![image.png](/img/bVcRFNg)                   limit:示意一次Scan扫描的行数,相当于MySql的limit。**须要留神的是:此参数值在2.x版本失效,1.x版本没有此参数。**         默认值是-1。如果是默认值,则不会应用该参数。呈现这个问题的起因是Hbase-client采纳的是2.x版本,然而Hbase服务端是1.x版本。应用limit参数对其有效。所以会一次去服务端查问Integer.MAX_VALUE条数据,导致OOM和timeout。           在结构Hbase服务端的申请参数时,代码别离如下(能够看到2.x多了limitOfRows参数):2.x版本:
public static ScanRequest buildScanRequest(byte[] regionName, Scan scan, int numberOfRows,      boolean closeScanner) throws IOException {    ScanRequest.Builder builder = ScanRequest.newBuilder();    RegionSpecifier region = buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName);    builder.setNumberOfRows(numberOfRows);    builder.setCloseScanner(closeScanner);    builder.setRegion(region);    builder.setScan(ProtobufUtil.toScan(scan));    builder.setClientHandlesPartials(true);    builder.setClientHandlesHeartbeats(true);    builder.setTrackScanMetrics(scan.isScanMetricsEnabled());    if (scan.getLimit() > 0) {      builder.setLimitOfRows(scan.getLimit());    }    return builder.build();  }

在1.x版本:

  public static ScanRequest buildScanRequest(final byte[] regionName, final Scan scan,      final int numberOfRows, final boolean closeScanner) throws IOException {    ScanRequest.Builder builder = ScanRequest.newBuilder();    RegionSpecifier region = buildRegionSpecifier(      RegionSpecifierType.REGION_NAME, regionName);    builder.setNumberOfRows(numberOfRows);    builder.setCloseScanner(closeScanner);    builder.setRegion(region);    builder.setScan(ProtobufUtil.toScan(scan));    builder.setClientHandlesPartials(true);    builder.setClientHandlesHeartbeats(true);    builder.setTrackScanMetrics(scan.isScanMetricsEnabled());    return builder.build();  }

踩坑2:在进行Scan扫描的时候,随着工夫的推移,Scan的速度越来越慢。
剖析:Scan有2个参数:

  startRow:扫描的起始rowkey。  filter:值过滤器,比方:RowFilter。 其解决代码如下:
byte[] startRow = scan.getStartRow();   if (startRow != null && startRow.length > 0) {     scanBuilder.setStartRow(ByteStringer.wrap(startRow));   }   byte[] stopRow = scan.getStopRow();   if (stopRow != null && stopRow.length > 0) {     scanBuilder.setStopRow(ByteStringer.wrap(stopRow));   }   if (scan.hasFilter()) {     scanBuilder.setFilter(ProtobufUtil.toFilter(scan.getFilter()));   }

在应用scan进行全表扫描的时候,如果没有指定startRow,那么就会越来越慢。因为每次都是从头开始扫描,所以会越来越慢。
所以startRow尽量都要增加上。