1. 程式人生 > >Hbase Scan的重要引數

Hbase Scan的重要引數

  Scan是操作Hbase中非常常用的一個操作,雖然前面的Hbase API操作簡單的介紹了Scan的操作,但不夠詳細,由於Scan非常常用,關於其詳細的整理也是很有必要的。

  Scan

  HBase中的資料表通過劃分成一個個的Region來實現資料的分片,每一個Region關聯一個RowKey的範圍區間,而每一個Region中的資料,按RowKey的字典順序進行組織。

  正是基於這種設計,使得HBase能夠輕鬆應對這類查詢:“指定一個RowKey的範圍區間,獲取該區間的所有記錄”, 這類查詢在HBase被稱之為Scan。

  1 . 構建Scan,指定startRow與stopRow,如果未指定的話會進行全表掃描

  2 . 獲取ResultScanner

  3 . 遍歷查詢結果

  4 . 關閉ResultScanner

  public void stringFilter() throws IOException { Configuration conf = HBaseConfiguration.create(); // 獲取Table例項 HTable table = new HTable(conf, user); // 構建Scan Scan scan = new Scan(); scan = scan.setStartRow(Bytes.toBytes(startRowxxx)).setStopRow(Bytes.toBytes(StopRowxxx)); RowFilter filter = new RowFilter( CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(224382618261914241)) ); scan.setFilter(filter); // 獲取resultScanner ResultScanner scanner = table.getScanner(scan); Result result = null; // 處理結果 while ((result = scanner.next()) != null) { byte[] value = result.getValue(Bytes.toBytes(ship), Bytes.toBytes(addr)); if (value == null || value.length == 0) { continue; } System.out.println( new String(value) ); System.out.println(hello World); } // 關閉ResultScanner scanner.close(); table.close(); }

  其它的設定引數

  Caching: 設定一次RPC請求批量讀取的Results數量

  下面的示例程式碼設定了一次讀取回來的Results數量為100:

  scan.setCaching(100);

  Client每一次往RegionServer傳送scan請求,都會批量拿回一批資料(由Caching決定過了每一次拿回的Results數量),然後放到本次的Result Cache中:

  

 

  應用每一次讀取資料時,都是從本地的Result Cache中獲取的。如果Result Cache中的資料讀完了,則Client會再次往RegionServer傳送scan請求獲取更多的資料。

  Batch: 設定每一個Result中的列的數量

  下面的示例程式碼設定了每一個Result中的列的數量的限制值為3:

  scan.setBatch(3);

  該引數適用於一行資料過大的場景,這樣,一行資料被請求的列會被拆成多個Results返回給Client。

  舉例說明如下:

  假設一行資料中共有十個列:

  {Col01,Col02,Col03,Col04,Col05,Col06,Col07,Col08,Col09, Col10}

  假設Scan中設定的Batch為3,那麼,這一行資料將會被拆成4個Results返回:

  Result1 - {Col01,Col02,Col03}Result2 - {Col04,Col05,Col06}Result3 - {Col07,Col08,Col09}Result4 - {Col10}

  關於Caching引數,我們說明了是Client每一次從RegionServer側獲取到的Results的數量,上例中,一行資料被拆成了4個Results,這將會導致Caching中的計數器被減了4次。結合Caching與Batch,我們再列舉一個稍複雜的例子:

  假設,Scan的引數設定如下:

  final byte[] start = Bytes.toBytes(“Row1”);

  final byte[] stop = Bytes.toBytes(“Row5”);

  Scan scan = new Scan();

  scan.withStartRow(start).withStopRow(stop);

  scan.setCaching(10);

  scan.setBatch(3);

  待讀取的資料RowKey與所關聯的列集如下所示:

  Row1: {Col01,Col02,Col03,Col04,Col05,Col06,Col07,Col08,Col09,Col10}

  Row2: {Col01,Col02,Col03,Col04,Col05,Col06,Col07,Col08,Col09,Col10,Col11}

  Row3: {Col01,Col02,Col03,Col04,Col05,Col06,Col07,Col08,Col09,Col10}

  再回顧一下Caching與Batch的定義:

  Caching: 影響一次讀取返回的Results數量。

  Batch: 限定了一個Result中所包含的列的數量,如果一行資料被請求的列的數量超出Batch限制,那麼這行資料會被拆成多個Results。

  那麼, Client往RegionServer第一次請求所返回的結果集如下所示:

  Result1 - Row1: {Col01,Col02,Col03}

  Result2 - Row1: {Col04,Col05,Col06}

  Result3 - Row1: {Col07,Col08,Col09}

  Result4 - Row1: {Col10}

  Result5 - Row2: {Col01,Col02,Col03}

  Result6 - Row2: {Col04,Col05,Col06}

  Result7 - Row2: {Col07,Col08,Col09}

  Result8 - Row2: {Col10,Col11}

  Result9 - Row3: {Col01,Col02,Col03}

  Result10 - Row3: {Col04,Col05,Col06}

  Limit: 限制一次Scan操作所獲取的行的數量

  同SQL語法中的limit子句,限制一次Scan操作所獲取的行的總量:

  scan.setLimit(10000);

  注意:Limit引數是在2.0版本中新引入的。但在2.0.0版本中,當Batch與Limit同時設定時,似乎還存在一個BUG,初步分析問題原因應該與BatchScanResultCache中的numberOfCompletedRows計數器邏輯處理有關。因此,暫時不建議同時設定這兩個引數。

  CacheBlock: RegionServer側是否要快取本次Scan所涉及的HFileBlocks

  scan.setCacheBlocks(true);

  e) Raw Scan: 是否可以讀取到刪除標識以及被刪除但尚未被清理的資料

  scan.setRaw(true);

  MaxResultSize: 從記憶體佔用量的維度限制一次Scan的返回結果集

  下面的示例程式碼將返回結果集的最大值設定為5MB:

  scan.setMaxResultSize(5 * 1024 * 1024);

  Reversed Scan: 反向掃描

  普通的Scan操作是按照字典順序從小到大的順序讀取的,而Reversed Scan則恰好相反:

  scan.setReversed(true);

  帶Filter的Scan

  Filter可以在Scan的結果集基礎之上,對返回的記錄設定更多條件值,這些條件可以與RowKey有關,可以與列名有關,也可以與列值有關,還可以將多個Filter條件組合在一起,等等。

  最常用的Filter是SingleColumnValueFilter,基於它,可以實現如下類似的查詢:

  “返回滿足條件{列I:D的值大於等於10}的所有行”

  示例程式碼如下:

  Filter豐富了HBase的查詢能力,但使用Filter之前,需要注意一點:Filter可能會導致查詢響應時延變的不可控制。因為我們無法預測,為了找到一條符合條件的記錄,背後需要掃描多少資料量,如果在有效限制了Scan範圍區間(通過設定StartRow與StopRow限制)的前提下,該問題能夠得到有效的控制。這些資訊都要求使用Filter之前應該詳細調研自己的業務資料模型。