1. 程式人生 > >Hbase中內建Filter詳解

Hbase中內建Filter詳解

一、建表

1、表名:“ORDER_TABLE

2、列簇:“user”,“order”,“item

3、表結構如下:

 

二、封裝服務

服務程式碼如下:

@Override
	public String get(String tableName, Filter filter) {
		Scan scan = new Scan();
		scan.setFilter(filter);
		return htemplate.find(tableName, scan, new ResultsExtractor<String>() {

			@Override
			public String extractData(ResultScanner results) throws Exception {
				for(Result res : results){  
		            for(Cell cell : res.rawCells()){  
		                System.out.println("KV: " + cell + ", Value: " + Bytes.toString(CellUtil.cloneValue(cell)));  
		            }  
		            System.out.println("------------------------------------------------------------");  
		        }
				return "chhliu";
			}
		});
	}

三、內建Filter的使用

Hbase中支援的內建Filter列表如下:


1、RowFilter使用

說明:篩選出匹配的所有的行,支援基於行鍵過濾資料,可以執行精確匹配,子字串匹配或正則表示式匹配,過濾掉不匹配的資料。

用法:使用BinaryComparator可以篩選出具有某個行鍵的行,或者通過改變比較運算子來篩選出符合某一條件的多條資料

示例:

Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("firstRow")));

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu
KV: firstRow/order:num/1479788660941/Put/vlen=1/mvcc=0, Value: 1
KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/user:address/1479788610153/Put/vlen=9/mvcc=0, Value: chongqing
KV: firstRow/user:name/1479788577571/Put/vlen=6/mvcc=0, Value: chhliu
KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456

從測試結果可以看出,掃描出了所有“firstRow”行的資料。

總結:

RowFilter的使用關鍵在於CompareFilter.CompareOp這個內部列舉類,該類的定義如下:

@InterfaceAudience.Public
  @InterfaceStability.Stable
  public enum CompareOp {
    /** less than */
    LESS,  // 檢查是否小於比較器裡的值
    /** less than or equal to */
    LESS_OR_EQUAL,  // 檢查是否小於或等於比較器裡的值
    /** equals */
    EQUAL,  // 檢查是否等於比較器裡的值
    /** not equal */
    NOT_EQUAL, // 檢查是否不等於比較器裡的值
    /** greater than or equal to */
    GREATER_OR_EQUAL,  // 檢查是否大於或等於比較器裡的值
    /** greater than */
    GREATER,  // 檢查是否大於比較器裡的值
    /** no operation */
    NO_OP,  // 預設返回false,因此過濾掉所有的資料
  }

該列舉類定義了7中比較運算子,供我們掃描操作

2、QualifierFilter使用

說明:該Filter是一種類似RowFilter的比較過濾器,不同之處是它用來匹配列限定符而不是行健

示例:

Filter filter = new QualifierFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("name"));

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/user:name/1479788577571/Put/vlen=6/mvcc=0, Value: chhliu
------------------------------------------------------------
KV: secondRow/item:name/1479788846563/Put/vlen=4/mvcc=0, Value: kuzi
KV: secondRow/user:name/1479788961691/Put/vlen=6/mvcc=0, Value: xyh123
從上面的測試結果可以看出,掃描出了所有的列名為“name”的列資料。

3、PrefixFilter使用

說明:這是RowFilter的一種特例,它基於行健的字首值進行過濾,它相當於給掃描建構函式Scan(byte[] startRow, byte[] stopRow),提供了一個停止鍵,只是你不需要自己計算停止鍵。

示例:

Filter filter = new PrefixFilter(Bytes.toBytes("second"));

測試結果:

KV: secondRow/item:name/1479788846563/Put/vlen=4/mvcc=0, Value: kuzi
KV: secondRow/item:price/1479788812565/Put/vlen=2/mvcc=0, Value: 50
KV: secondRow/item:type/1479788825867/Put/vlen=4/mvcc=0, Value: yifu
KV: secondRow/order:num/1479788793253/Put/vlen=1/mvcc=0, Value: 3
KV: secondRow/order:payType/1479788873259/Put/vlen=4/mvcc=0, Value: cash
KV: secondRow/order:totalPrice/1479788888925/Put/vlen=3/mvcc=0, Value: 150
KV: secondRow/user:address/1479788916089/Put/vlen=7/mvcc=0, Value: chengdu
KV: secondRow/user:name/1479788961691/Put/vlen=6/mvcc=0, Value: xyh123
KV: secondRow/user:password/1479788935711/Put/vlen=10/mvcc=0, Value: 1234567890

從上面的測試結果可以看出,所有“second”字首的行的資料都被掃描出來了。

4、KeyOnlyFilter使用

說明:這個Filter只會返回每行的行鍵+列簇+列,而不返回值,對不需要值的應用場景來說,非常實用,減少了值的傳遞。

示例:

Filter filter = new KeyOnlyFilter();

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/item:price/1479788739567/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/item:type/1479788725903/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/order:num/1479788660941/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/order:payType/1479788691846/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/user:address/1479788610153/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/user:name/1479788577571/Put/vlen=0/mvcc=0, Value: 
KV: firstRow/user:password/1479788593494/Put/vlen=0/mvcc=0, Value: 
------------------------------------------------------------
KV: secondRow/item:name/1479788846563/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/item:price/1479788812565/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/item:type/1479788825867/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/order:num/1479788793253/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/order:payType/1479788873259/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/order:totalPrice/1479788888925/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/user:address/1479788916089/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/user:name/1479788961691/Put/vlen=0/mvcc=0, Value: 
KV: secondRow/user:password/1479788935711/Put/vlen=0/mvcc=0, Value:

從上面的測試結果,可以看出,Value對應的值都為空。

5、TimestampsFilter使用

說明:該過濾器允許針對返回給客戶端的時間版本進行更細粒度的控制,使用的時候,可以提供一個返回的時間戳的列表,只有與時間戳匹配的單元才可以返回。當做多行掃描或者是單行檢索時,如果需要一個時間區間,可以在GetScan物件上使用setTimeRange()方法來實現這一點。

示例:

List<Long> timestamps = new ArrayList<Long>();
timestamps.add(1479788961691L);
timestamps.add(1479788676517L);
timestamps.add(1479788812565L);
Filter filter = new TimestampsFilter(timestamps);

測試結果:

KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
-----------------------------------------------------------
KV: secondRow/item:price/1479788812565/Put/vlen=2/mvcc=0, Value: 50
KV: secondRow/user:name/1479788961691/Put/vlen=6/mvcc=0, Value: xyh123

從上面的測試結果中,可以看出,返回了時間戳列表中對應的列資料。

6、FirstKeyOnlyFilter使用

說明:該Filter的作用,是找每一行的第一列資料,找到之後,就會停止掃描。

示例:

Filter filter = new FirstKeyOnlyFilter();

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
------------------------------------------------------------
KV: secondRow/item:name/1479788846563/Put/vlen=4/mvcc=0, Value: kuzi
------------------------------------------------------------

從上面的測試結果中,只掃描出了“firstRow”和“secondRow”的第一行資料。

7、ColumnPrefixFilter使用

說明:該Filter是按照列名的字首來掃描單元格的,只會返回符合條件的列資料

示例:

Filter filter = new ColumnPrefixFilter(Bytes.toBytes("pay"));

測試結果:

KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
------------------------------------------------------------
KV: secondRow/order:payType/1479788873259/Put/vlen=4/mvcc=0, Value: cash
------------------------------------------------------------

從上面的測試結果可以看出,將列名中帶“pay”字首的列都掃描出來了。

8、ValueFilter使用

說明:該Filter主要是對值進行過濾,用法和RowFilter類似,只不過側重點不同而已,針對的是單元值,使用這個過濾器可以過濾掉不符合設定標準的所有單元

示例:

Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("100")));

測試結果:

KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100

從上面的測試結果中,我們可以看出,將Value100的列都掃描出來了。

在這裡,著重說下ComparatorHbase提供的內建的Comparator有如下幾個:


BinaryComparator:會比較給定的值和掃描的值進行比對,如果一致則返回,使用Bytes.compareTo()方法比較。

BinaryPrefixComparator:如果掃描的值中帶有給定的字首,就會返回,使用Bytes.compareTo()方法,從左開始執行基於字首的位元組級比較示例如下:

@Test
public void testValueFilterBinaryPrefixComparator(){
Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("cheng")));
hService.get("ORDER_TABLE", filter);
}

測試結果如下:

KV: secondRow/user:address/1479788916089/Put/vlen=7/mvcc=0, Value: chengdu

從測試結果可以看出,返回了字首為“cheng”的列資料

NullComparator:檢查給定值是否為空。

BitComparator:執行按位比較。

RegexStringComparator:把傳遞的值與比較器例項化時提供的正則表示式比較。

SubstringComparator:通過執行contains()方法,檢查傳遞的值是否包含比較器提供的子字串示例如下:

@Test

public void testValueFilterSubstringComparator(){
Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("123456"));
hService.get("ORDER_TABLE", filter);
}

測試結果如下:

KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456
------------------------------------------------------------
KV: secondRow/user:password/1479788935711/Put/vlen=10/mvcc=0, Value: 1234567890

從上面的測試結果中,可以看出,只要是值中包含了“123456”字串的結果,都返回了。

9、ColumnCountGetFilter使用

說明:該Filter用來返回每行最多返回多少列,但返回的總數不超過設定的列數

示例:

Filter filter = new ColumnCountGetFilter(2);

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100

從上面的測試結果可以看出,總共返回了第一行的2

10、SingleColumnValueFilter使用

說明:根據列的值來決定這一行資料是否返回,落腳點在行,而不是列。我們可以設定filter.setFilterIfMissing(true);如果為true,當這一列不存在時,不會返回,如果為false,當這一列不存在時,會返回所有的列資訊。

先來測試這一列存在的情況,當列存在時,無論設定成true或者是false,測試結果沒有影響

示例:

SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("user"), Bytes.toBytes("name"), CompareFilter.CompareOp.EQUAL, new SubstringComparator("chh"));
filter.setFilterIfMissing(false);// 預設情況下為false

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu
KV: firstRow/order:num/1479788660941/Put/vlen=1/mvcc=0, Value: 1
KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/user:address/1479788610153/Put/vlen=9/mvcc=0, Value: chongqing
KV: firstRow/user:name/1479788577571/Put/vlen=6/mvcc=0, Value: chhliu
KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456

從上面的測試結果可以看出,當前列“name”存在,且字首“chh”存在掃描的值“chhliu”中,而該值存在第一行中,所以返回第一行的所有資料。

下面來看下列不存在的情況下,設定成true或者是false的區別

示例:

SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("user"), Bytes.toBytes("xyh"), CompareFilter.CompareOp.EQUAL, new SubstringComparator("chh"));
filter.setFilterIfMissing(false);// 預設情況下為false

測試結果如下:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu
KV: firstRow/order:num/1479788660941/Put/vlen=1/mvcc=0, Value: 1
KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/user:address/1479788610153/Put/vlen=9/mvcc=0, Value: chongqing
KV: firstRow/user:name/1479788577571/Put/vlen=6/mvcc=0, Value: chhliu
KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456
------------------------------------------------------------
KV: secondRow/item:name/1479788846563/Put/vlen=4/mvcc=0, Value: kuzi
KV: secondRow/item:price/1479788812565/Put/vlen=2/mvcc=0, Value: 50
KV: secondRow/item:type/1479788825867/Put/vlen=4/mvcc=0, Value: yifu
KV: secondRow/order:num/1479788793253/Put/vlen=1/mvcc=0, Value: 3
KV: secondRow/order:payType/1479788873259/Put/vlen=4/mvcc=0, Value: cash
KV: secondRow/order:totalPrice/1479788888925/Put/vlen=3/mvcc=0, Value: 150
KV: secondRow/user:address/1479788916089/Put/vlen=7/mvcc=0, Value: chengdu
KV: secondRow/user:name/1479788961691/Put/vlen=6/mvcc=0, Value: xyh123
KV: secondRow/user:password/1479788935711/Put/vlen=10/mvcc=0, Value: 1234567890

從上面的測試結果可以看出,當列“xyh”不存在是,設定成false時,會返回所有的行資料,當我們把false換成true測試時,會發現,沒有返回任何資料。

11、SingleColumnValueExcludeFilter使用

說明:該FilterSingleColumnValueFilter作用類似,唯一的區別在於,返回的資料不包含掃描條件的列。

示例:

Filter filter = new SingleColumnValueExcludeFilter(Bytes.toBytes("user"), Bytes.toBytes("name"), CompareFilter.CompareOp.EQUAL, new SubstringComparator("chh"));

測試結果:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu
KV: firstRow/order:num/1479788660941/Put/vlen=1/mvcc=0, Value: 1
KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/user:address/1479788610153/Put/vlen=9/mvcc=0, Value: chongqing
KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456

從上面的測試結果可以看出,返回的結果總共只有8列的資料,沒有掃描條件包含的那一列資料。

12、FilterList使用

說明:

示例:

Filter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("firstRow"))); // OK 篩選出匹配的所有的行  
Filter valueFilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("yifu")));
List<Filter> listFilter = new ArrayList<Filter>();
listFilter.add(rowFilter);
listFilter.add(valueFilter);
Filter filter = new FilterList(listFilter);

測試結果:

KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu

從上面的測試結果可以看出,firstRowsecondRow中都存在值為“yifu”,但是通過兩個過濾器限定後,符合條件的只有firstRow中的“yifu”這一列。FilterList還支援多Filter的“AND”和“OR”操作,示例如下:

Filter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("firstRow"))); // OK 篩選出匹配的所有的行  
Filter valueFilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("yifu")));
List<Filter> listFilter = new ArrayList<Filter>();
listFilter.add(rowFilter);
listFilter.add(valueFilter);
Filter filter = new FilterList(FilterList.Operator.MUST_PASS_ONE, listFilter);

測試結果如下:

KV: firstRow/item:name/1479788712670/Put/vlen=5/mvcc=0, Value: maoyi
KV: firstRow/item:price/1479788739567/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/item:type/1479788725903/Put/vlen=4/mvcc=0, Value: yifu
KV: firstRow/order:num/1479788660941/Put/vlen=1/mvcc=0, Value: 1
KV: firstRow/order:payType/1479788691846/Put/vlen=5/mvcc=0, Value: check
KV: firstRow/order:totalPrice/1479788676517/Put/vlen=3/mvcc=0, Value: 100
KV: firstRow/user:address/1479788610153/Put/vlen=9/mvcc=0, Value: chongqing
KV: firstRow/user:name/1479788577571/Put/vlen=6/mvcc=0, Value: chhliu
KV: firstRow/user:password/1479788593494/Put/vlen=6/mvcc=0, Value: 123456
------------------------------------------------------------
KV: secondRow/item:type/1479788825867/Put/vlen=4/mvcc=0, Value: yifu

AND”還是“OR”通過FilterList.Operator.MUST_PASS_ONE來指定,如果是MUST_PASS_ONR,則是“OR”的關係,如果是MUST_PASS_ALL,則是“AND”的關係,如果不傳入這個引數,則預設為“AND”的關係。上面的測試中,使用的是“OR”的關係,也就是說,只要滿足“firstRow”或者是“yifu”中的任意一個條件,都會被掃描出來。