Hbase批量查詢-scan介紹

1.scan原理

HBase的查詢實現只提供兩種方式:

1、按指定RowKey 獲取唯一一條記錄,get方法(org.apache.hadoop.hbase.client.Get)

Get 的方法處理分兩種 : 設置了ClosestRowBefore 和沒有設置的rowlock .主要是用來保證行的事務性,即每個get 是以一個row 來標記的.一個row中可以有很多family 和column.

 

2、按指定的條件獲取一批記錄,scan方法(org.apache.Hadoop.hbase.client.Scan)實現條件查詢功能使用的就是scan 方式.

1)scan 可以通過setCaching 與setBatch 方法提高速度(以空間換時間);

2)scan 可以通過setStartRow 與setEndRow 來限定範圍([start,end)start 是閉區間,

end 是開區間)。範圍越小,性能越高。

3)、scan 可以通過setFilter 方法添加過濾器,這也是分頁、多條件查詢的基礎。

 

HBase中scan並不像大家想象的一樣直接發送一個命令過去,服務器就將滿足掃描條件的所有數據一次性返回給客戶端。而實際上它的工作原理如下圖所示:

上圖右側是HBase scan的客戶端代碼,其中for循環中每次遍歷ResultScanner對象獲取一行記錄,實際上在客戶端層面都會調用一次next請求。next請求整個流程可以分爲如下幾個步驟:

  • next請求首先會檢查客戶端緩存中是否存在還沒有讀取的數據行,如果有就直接返回,否則需要將next請求給HBase服務器端(RegionServer)。
  • 如果客戶端緩存已經沒有掃描結果,就會將next請求發送給HBase服務器端。默認情況下,一次next請求僅可以請求100行數據(或者返回結果集總大小不超過2M)
  • 服務器端接收到next請求之後就開始從BlockCache、HFile以及memcache中一行一行進行掃描,掃描的行數達到100行之後就返回給客戶端,客戶端將這100條數據緩存到內存並返回一條給上層業務。

 

HBase 每次 scan 的數據量可能會比較大,客戶端不會一次性全部把數據從服務端拉回來。而是通過多次 rpc 分批次的拉取。類似於 TCP 協議裏面一段一段的傳輸,可以做到細粒度的流量控制。至於如何調優,控制每次 rpc 拉取的數據量,就可以通過三個參數來控制。

 

.setCaching => .setNumberOfRowsFetchSize (客戶端每次 rpc fetch 的行數)

.setBatch => .setColumnsChunkSize (客戶端每次獲取的列數)

.setMaxResultSize => .setMaxResultByteSize (客戶端緩存的最大字節數)

 

  • hbase.client.scanner.caching - (setCaching):HBase-0.98 默認值爲爲 100,HBase-1.2 默認值爲 2147483647,即 Integer.MAX_VALUE。Scan.next() 的一次 RPC 請求 fetch 的記錄條數。配置建議:這個參數與下面的setMaxResultSize配合使用,在網絡狀況良好的情況下,自定義設置不宜太小, 可以直接採用默認值,不配置。
  • setBatch() 配置獲取的列數,假如表有兩個列簇 cf,info,每個列簇5個列。這樣每行可能有10列了,setBatch() 可以控制每次獲取的最大列數,進一步從列級別控制流量。配置建議:當列數很多,數據量大時考慮配置此參數,例如100列每次只獲取50列。一般情況可以默認值(-1 不受限)。
  • hbase.client.scanner.max.result.size - (setMaxResultSize):HBase-0.98 無該項配置,HBase-1.2 默認值爲 210241024,即 2M。Scan.next() 的一次 RPC 請求 fetch 的數據量大小,目前 HBase-1.2 在 Caching 爲默認值(Integer Max)的時候,實際使用這個參數控制 RPC 次數和流量。配置建議:如果網絡狀況較好(萬兆網卡),scan 的數據量非常大,可以將這個值配置高一點。如果配置過高:則可能 loadCache 速度比較慢,導致 scan timeout 異常
  • hbase.server.scanner.max.result.size:服務端配置。HBase-0.98 無該項配置,HBase-1.2 新增,默認值爲 10010241024,即 100M。該參數表示當 Scan.next() 發起 RPC 後,服務端返回給客戶端的最大字節數,防止 Server OOM。

 

要計算一次掃描操作的RPC請求的次數,用戶需要先計算出行數和每行列數的乘積。然後用這個值除以批量大小和每行列數中較小的那個值。最後再用除得的結果除以掃描器緩存值。 用數學公式表示如下:

RPC 返回的個數  = (row數 * 每行的列數)/ Min(每行列數,Batch大小) / Caching大小 
Result 返回的個數 =( row數 * 每行的列數 )/ Min(每行列數,Batch大小)

 

2.Hbase Shell中使用

在hbase shell中查詢數據,可以在hbase shell中直接使用過濾器:

# hbase shell > scan 'tablename',STARTROW=>'start',COLUMNS=>['family:qualifier'],FILTER=>"ValueFilter(=,'substring:88')"

如上命令所示,查詢的是表名爲testByCrq,過濾方式是通過value過濾,匹配出value含111的數據。

因在hbase shell中一些操作比較麻煩(比如刪除字符需先按住ctrl在點擊退格鍵),且退出後,查詢的歷史紀錄不可考,故如下方式是比較方便的一種:

# echo "scan 'testByCrq', FILTER=>\"ValueFilter(=,'substring:111')\"" | hbase shell

如上命令,可在bash中直接使用,表名是testByCrq,過濾方式是通過value過濾,匹配出value含111的數據,中間的"需要用\轉義。

 

建表

create 'test1', 'lf', 'sf' 
-- lf: column family of LONG values (binary value) 
-- sf: column family of STRING values

導入數據

put 'test1', 'user1|ts1', 'sf:c1', 'sku1' 
put 'test1', 'user1|ts2', 'sf:c1', 'sku188' 
put 'test1', 'user1|ts3', 'sf:s1', 'sku123' 
put 'test1', 'user2|ts4', 'sf:c1', 'sku2' 
put 'test1', 'user2|ts5', 'sf:c2', 'sku288' 
put 'test1', 'user2|ts6', 'sf:s1', 'sku222' 
put 'test1', 'user3|ts7', 'lf:c1', 12345 
put 'test1', 'user3|ts8', 'lf:c1', 67890

 

1.限制條件

scan 'hbase:meta' 
scan 'hbase:meta', {COLUMNS => 'info:regioninfo'} 
scan 'ns1:t1', {COLUMNS => ['c1', 'c2'], LIMIT => 10, STARTROW => 'xyz'} 
scan 't1', {COLUMNS => ['c1', 'c2'], LIMIT => 10, STARTROW => 'xyz'} 
scan 't1', {COLUMNS => 'c1', TIMERANGE => [1303668804, 1303668904]} 
scan 't1', {REVERSED => true}

 

2.Filter過濾

1.rowkey查詢

rowkey爲user1開頭的

scan 'test1', FILTER => "PrefixFilter ('user1')" 
 ROW       COLUMN+CELL 
user1|ts1 column=sf:c1, timestamp=1409122354868, value=sku1 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=sku188 
user1|ts3 column=sf:s1, timestamp=1409122354954, value=sku123

FirstKeyOnlyFilter: 一個rowkey可以有多個version,同一個rowkey的同一個column也會有多個的值, 只拿出key中的第一個column的第一個version KeyOnlyFilter: 只要key,不要value

scan 'test1', FILTER=>"FirstKeyOnlyFilter() AND ValueFilter(=,'binary:sku188') AND KeyOnlyFilter()" 
 ROW       COLUMN+CELL 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=

查詢rowkey裏面包含ts3的

scan 'test1', FILTER=>"RowFilter(=,'substring:ts3')" 
ROW COLUMN+CELL 
user1|ts3 column=sf:s1, timestamp=1554865926412, value=sku123

 

從user1|ts2開始,找到所有的rowkey以user1開頭的

scan 'test1', {STARTROW=>'user1|ts2', FILTER => "PrefixFilter ('user1')"} 
ROW COLUMN+CELL 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=sku188 
user1|ts3 column=sf:s1, timestamp=1409122354954, value=sku123

從user1|ts2開始,找到所有的到rowkey以user2開頭

scan 'test1', {STARTROW=>'user1|ts2', STOPROW=>'user2'} 
ROW COLUMN+CELL 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=sku188 user1|ts3 column=sf:s1, timestamp=1409122354954, value=sku123

 

2.值查詢

誰的值=sku188

scan 'test1', FILTER=>"ValueFilter(=,'binary:sku188')" 
ROW COLUMN+CELL 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=sku188

誰的值包含88

scan 'test1', FILTER=>"ValueFilter(=,'substring:88')" 
ROW COLUMN+CELL 
user1|ts2 column=sf:c1, timestamp=1409122354918, value=sku188 
user2|ts5 column=sf:c2, timestamp=1409122355030, value=sku288

值小於等於20000

scan 'test1', FILTER=>"ValueFilter(<=,'binary:20000')" 
ROW COLUMN+CELL 
user3|ts7 column=lf:c1, timestamp=1554866187587, value=12345

注意:如果查詢值大於20000,會查出所有值,因爲“sku188”等值轉爲二進制後都大於20000。

substring不能使用小於等於等符號。

 

3.列查詢

column爲c2,值包含88的用戶

scan 'test1', FILTER=>"ColumnPrefixFilter('c2') AND ValueFilter(=,'substring:88')" 
ROW COLUMN+CELL 
user2|ts5 column=sf:c2, timestamp=1409122355030, value=sku288

通過搜索進來的(column爲s)值包含123或者222的用戶

scan 'test1', FILTER=>"ColumnPrefixFilter('s') AND ( ValueFilter(=,'substring:123') OR ValueFilter(=,'substring:222') )" 
ROW COLUMN+CELL 
user1|ts3 column=sf:s1, timestamp=1409122354954, value=sku123 
user2|ts6 column=sf:s1, timestamp=1409122355970, value=sku222

列族查詢

scan 'test1', FILTER=>"FamilyFilter(=,'substring:lf')" 
ROW COLUMN+CELL 
user3|ts7 column=lf:c1, timestamp=1554866187587, value=12345 
user3|ts8 column=lf:c1, timestamp=1554866294485, value=67890

 

4.時間戳

scan 'test1',{FILTER=>"TimestampsFilter(1448069941270,1548069941230)" }

 

3.java查詢

過濾器

HBase 的基本 API,包括增、刪、改、查等。

增、刪都是相對簡單的操作,與傳統的 RDBMS 相比,這裏的查詢操作略顯蒼白,只能根據特性的行鍵進行查詢(Get)或者根據行鍵的範圍來查詢(Scan)。

HBase 不僅提供了這些簡單的查詢,而且提供了更加高級的過濾器(Filter)來查詢。

 

過濾器的兩類參數

過濾器可以根據列族、列、版本等更多的條件來對數據進行過濾,基於 HBase 本身提供的三維有序(行鍵,列,版本有序),這些過濾器可以高效地完成查詢過濾的任務,帶有過濾器條件的 RPC 查詢請求會把過濾器分發到各個 RegionServer(這是一個服務端過濾器),這樣也可以降低網絡傳輸的壓力。

使用過濾器至少需要兩類參數:

 

  • 一類是抽象的操作符

HBase 提供了枚舉類型的變量來表示這些抽象的操作符:

LESS

LESS_OR_EQUAL

EQUAL

NOT_EQUAL

GREATER_OR_EQUAL

GREATER

NO_OP

 

  • 另一類是比較器

代表具體的邏輯,例如字節級的比較,字符串級的比較等。

參數基礎

有兩個參數類在各類Filter中經常出現,統一介紹下:

(1)比較運算符 CompareFilter.CompareOp

比較運算符用於定義比較關係,可以有以下幾類值供選擇:

EQUAL                                  相等

GREATER                              大於

GREATER_OR_EQUAL           大於等於

LESS                                      小於

LESS_OR_EQUAL                  小於等於

NOT_EQUAL                        不等於

 

(2)比較器  ByteArrayComparable

通過比較器可以實現多樣化目標匹配效果,比較器有以下子類可以使用:

BinaryComparator               匹配完整字節數組 

BinaryPrefixComparator     匹配字節數組前綴 

BitComparator

NullComparator

RegexStringComparator    正則表達式匹配

SubstringComparator        子串匹配

1,FilterList

FilterList 代表一個過濾器鏈,它可以包含一組即將應用於目標數據集的過濾器,過濾器間具有“與” FilterList.Operator.MUST_PASS_ALL 和“或” FilterList.Operator.MUST_PASS_ONE 關係。

官網實例代碼,兩個“或”關係的過濾器的寫法:

FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE); //數據只要滿足一組過濾器中的一個就可以

SingleColumnValueFilter filter1 = new SingleColumnValueFilter(cf,column,CompareOp.EQUAL,Bytes.toBytes("my value"));

list.add(filter1);

SingleColumnValueFilter filter2 = new SingleColumnValueFilter(cf,column,CompareOp.EQUAL,Bytes.toBytes("my other value"));

list.add(filter2);

Scan scan = new Scan();

scan.setFilter(list);

2,列值過濾器--SingleColumnValueFilter

SingleColumnValueFilter 用於測試列值相等 (CompareOp.EQUAL ), 不等 (CompareOp.NOT_EQUAL),或單側範圍 (e.g., CompareOp.GREATER)。

構造函數:

(1)比較的關鍵字是一個字符數組

SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, byte[] value)

(2)比較的關鍵字是一個比較器(比較器下一小節做介紹)

SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, ByteArrayComparable comparator)

注意:根據列的值來決定這一行數據是否返回,落腳點在行,而不是列。我們可以設置filter.setFilterIfMissing(true);如果爲true,當這一列不存在時,不會返回,如果爲false,當這一列不存在時,會返回所有的列信息

測試表user內容如下:

Table table = connection.getTable(TableName.valueOf("user"));

SingleColumnValueFilter scvf= new SingleColumnValueFilter(Bytes.toBytes("account"), Bytes.toBytes("name"),

CompareOp.EQUAL,"zhangsan".getBytes());

scvf.setFilterIfMissing(true); //默認爲false, 沒有此列的數據也會返回 ,爲true則只返回name=lisi的數據

Scan scan = new Scan();

scan.setFilter(scvf);

ResultScanner resultScanner = table.getScanner(scan);

for (Result result : resultScanner) {

    List<Cell> cells= result.listCells();

    for (Cell cell : cells) {

        String row = Bytes.toString(result.getRow());

        String family1 = Bytes.toString(CellUtil.cloneFamily(cell));

        String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));

        String value = Bytes.toString(CellUtil.cloneValue(cell));

        System.out.println("[row:"+row+"],[family:"+family1+"],[qualifier:"+qualifier+"]"+ ",[value:"+value+"],[time:"+cell.getTimestamp()+"]");

    }

}

如果setFilterIfMissing(true), 有匹配只會返回當前列所在的行數據,基於行的數據 country 也返回了,因爲他麼你的rowkey是相同的

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

如果setFilterIfMissing(false),有匹配的列的值相同會返回,沒有此列的 name的也會返回,, 不匹配的name則不會返回。

下面 紅色是匹配列內容的會返回,其他的不是account:name列也會返回,, name=lisi的不會返回,因爲不匹配。

[row:lisi_1495527849910],[family:account],[qualifier:idcard],[value:42963319861234561230],[time:1495556647872]

[row:lisi_1495527850111],[family:account],[qualifier:password],[value:123451231236],[time:1495556648013]

[row:lisi_1495527850114],[family:address],[qualifier:city],[value:黃埔],[time:1495556648017]

[row:lisi_1495527850136],[family:address],[qualifier:province],[value:shanghai],[time:1495556648041]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21],[time:1495556648045]

[row:lisi_1495527850154],[family:info],[qualifier:sex],[value:女],[time:1495556648056]

[row:lisi_1495527850159],[family:userid],[qualifier:id],[value:002],[time:1495556648060]

[row:wangwu_1495595824517],[family:userid],[qualifier:id],[value:009],[time:1495624624131]

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

[row:zhangsan_1495527850951],[family:address],[qualifier:province],[value:guangdong],[time:1495556648855]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

[row:zhangsan_1495527851080],[family:info],[qualifier:sex],[value:男],[time:1495556648983]

[row:zhangsan_1495527851095],[family:userid],[qualifier:id],[value:001],[time:1495556648996]

 

3 鍵值元數據

由於HBase 採用鍵值對保存內部數據,鍵值元數據過濾器評估一行的鍵(ColumnFamily:Qualifiers)是否存在 

 

3.1. 基於列族過濾數據的FamilyFilter

構造函數:

FamilyFilter(CompareFilter.CompareOp familyCompareOp, ByteArrayComparable familyComparator)

代碼如下:

public static ResultScanner getDataFamilyFilter(String tableName,String family) throws IOException{

Table table = connection.getTable(TableName.valueOf("user"));

FamilyFilter ff = new FamilyFilter(CompareOp.EQUAL ,

new BinaryComparator(Bytes.toBytes("account"))); //表中不存在account列族,過濾結果爲空

// new BinaryPrefixComparator(value) //匹配字節數組前綴

// new RegexStringComparator(expr) // 正則表達式匹配

// new SubstringComparator(substr)// 子字符串匹配

Scan scan = new Scan();

// 通過scan.addFamily(family) 也可以實現此操作

scan.setFilter(ff);

ResultScanner resultScanner = table.getScanner(scan);

return resultScanner;

}

測試結果:查詢的都是account列簇的內容

[row:lisi_1495527849910],[family:account],[qualifier:idcard],[value:42963319861234561230],[time:1495556647872]

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:lisi_1495527850111],[family:account],[qualifier:password],[value:123451231236],[time:1495556648013]

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

3.2. 基於限定符Qualifier(列)過濾數據的QualifierFilter

構造函數:

QualifierFilter(CompareFilter.CompareOp op, ByteArrayComparable qualifierComparator)

Table table = connection.getTable(TableName.valueOf("user"));

QualifierFilter ff = new QualifierFilter(

CompareOp.EQUAL , new BinaryComparator(Bytes.toBytes("name")));

// new BinaryPrefixComparator(value) //匹配字節數組前綴

// new RegexStringComparator(expr) // 正則表達式匹配

// new SubstringComparator(substr)// 子字符串匹配

Scan scan = new Scan();

// 通過scan.addFamily(family) 也可以實現此操作

scan.setFilter(ff);

ResultScanner resultScanner = table.getScanner(scan);

測試結果:只返回 name 的列內容

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

3.3. 基於列名(即Qualifier)前綴過濾數據的ColumnPrefixFilter  

( 該功能用QualifierFilter也能實現 )

構造函數:

ColumnPrefixFilter(byte[] prefix) 

Table table = connection.getTable(TableName.valueOf("user"));

ColumnPrefixFilter ff = new ColumnPrefixFilter(Bytes.toBytes("name"));

Scan scan = new Scan();

// 通過QualifierFilter的 newBinaryPrefixComparator也可以實現

scan.setFilter(ff);

ResultScanner resultScanner = table.getScanner(scan);

返回結果:

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

3.4. 基於多個列名(即Qualifier)前綴過濾數據的MultipleColumnPrefixFilter

MultipleColumnPrefixFilter 和 ColumnPrefixFilter 行爲差不多,但可以指定多個前綴

byte[][] prefixes = new byte[][] {Bytes.toBytes("name"), Bytes.toBytes("age")};

//返回所有行中以name或者age打頭的列的數據

MultipleColumnPrefixFilter ff = new MultipleColumnPrefixFilter(prefixes);

Scan scan = new Scan();

scan.setFilter(ff);

ResultScanner rs = table.getScanner(scan);

結果:

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21],[time:1495556648045]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

3.5. 基於列範圍過濾數據ColumnRangeFilter

構造函數:

ColumnRangeFilter(byte[] minColumn, boolean minColumnInclusive, byte[] maxColumn, boolean maxColumnInclusive)

參數解釋:

minColumn - 列範圍的最小值,如果爲空,則沒有下限;

minColumnInclusive - 列範圍是否包含minColumn ;

maxColumn - 列範圍最大值,如果爲空,則沒有上限;

maxColumnInclusive - 列範圍是否包含maxColumn 。

代碼:

Table table = connection.getTable(TableName.valueOf("user"));

byte[] startColumn = Bytes.toBytes("a");

byte[] endColumn = Bytes.toBytes("d");

//返回所有列中從a到d打頭的範圍的數據,

ColumnRangeFilter ff = new ColumnRangeFilter(startColumn, true, endColumn, true);

Scan scan = new Scan();

scan.setFilter(ff);

ResultScanner rs = table.getScanner(scan);

結果:返回列名開頭是a 到  d的所有列數據

[row:lisi_1495527850114],[family:address],[qualifier:city],[value:黃埔],[time:1495556648017]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21],[time:1495556648045]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

4. RowKey

當需要根據行鍵特徵查找一個範圍的行數據時,使用Scan的startRow和stopRow會更高效,但是,startRow和stopRow只能匹配行鍵的開始字符,而不能匹配中間包含的字符:

        byte[] startColumn = Bytes.toBytes("azha");

        byte[] endColumn = Bytes.toBytes("dddf");

        Scan scan = new Scan(startColumn,endColumn);

當需要針對行鍵進行更復雜的過濾時,可以使用RowFilter:

構造函數:

RowFilter(CompareFilter.CompareOp rowCompareOp, ByteArrayComparable rowComparator)

 

代碼:

Table table = connection.getTable(TableName.valueOf("user"));

RowFilter rf = new RowFilter(CompareOp.EQUAL ,

new SubstringComparator("zhangsan"));

// new BinaryPrefixComparator(value) //匹配字節數組前綴

// new RegexStringComparator(expr) // 正則表達式匹配

// new SubstringComparator(substr)// 子字符串匹配

Scan scan = new Scan();

scan.setFilter(rf);

ResultScanner rs = table.getScanner(scan);

結果:

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

[row:zhangsan_1495527850951],[family:address],[qualifier:province],[value:guangdong],[time:1495556648855]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

[row:zhangsan_1495527851080],[family:info],[qualifier:sex],[value:男],[time:1495556648983]

[row:zhangsan_1495527851095],[family:userid],[qualifier:id],[value:001],[time:1495556648996]

5.PageFilter

指定頁面行數,返回對應行數的結果集。

需要注意的是,該過濾器並不能保證返回的結果行數小於等於指定的頁面行數,因爲過濾器是分別作用到各個region server的,它只能保證當前region返回的結果行數不超過指定頁面行數。

構造函數:

PageFilter(long pageSize)

代碼:

Table table = connection.getTable(TableName.valueOf("user"));

PageFilter pf = new PageFilter(2L);

Scan scan = new Scan();

scan.setFilter(pf);

scan.setStartRow(Bytes.toBytes("zhangsan_"));

ResultScanner rs = table.getScanner(scan);

結果:返回的結果實際上有四條,因爲這數據來自不同RegionServer, 

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]

6.SkipFilter

根據整行中的每個列來做過濾,只要存在一列不滿足條件,整行都被過濾掉。

例如,如果一行中的所有列代表的是不同物品的重量,則真實場景下這些數值都必須大於零,我們希望將那些包含任意列值爲0的行都過濾掉。

在這個情況下,我們結合ValueFilter和SkipFilter共同實現該目的:

scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,new BinaryComparator(Bytes.toBytes(0))));

構造函數:

SkipFilter(Filter filter) 

代碼:

Table table = connection.getTable(TableName.valueOf("user"));

SkipFilter sf = new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,

new BinaryComparator(Bytes.toBytes("zhangsan"))));

Scan scan = new Scan();

scan.setFilter(sf);

ResultScanner rs = table.getScanner(scan);

結果:

[row:lisi_1495527849910],[family:account],[qualifier:idcard],[value:42963319861234561230],[time:1495556647872]

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:lisi_1495527850111],[family:account],[qualifier:password],[value:123451231236],[time:1495556648013]

[row:lisi_1495527850114],[family:address],[qualifier:city],[value:黃埔],[time:1495556648017]

[row:lisi_1495527850136],[family:address],[qualifier:province],[value:shanghai],[time:1495556648041]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21],[time:1495556648045]

[row:lisi_1495527850154],[family:info],[qualifier:sex],[value:女],[time:1495556648056]

[row:lisi_1495527850159],[family:userid],[qualifier:id],[value:002],[time:1495556648060]

[row:wangwu_1495595824517],[family:userid],[qualifier:id],[value:009],[time:1495624624131]

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]

[row:zhangsan_1495527850951],[family:address],[qualifier:province],[value:guangdong],[time:1495556648855]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

[row:zhangsan_1495527851080],[family:info],[qualifier:sex],[value:男],[time:1495556648983]

[row:zhangsan_1495527851095],[family:userid],[qualifier:id],[value:001],[time:1495556648996]

和原來數據相比  列值爲name的 zhagnsan的所在行的 rowkey   爲   zhangsan_1495527850824 在上面結果中是過濾了

[row:lisi_1495527849910],[family:account],[qualifier:idcard],[value:42963319861234561230]

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi]

[row:lisi_1495527850111],[family:account],[qualifier:password],[value:123451231236]

[row:lisi_1495527850114],[family:address],[qualifier:city],[value:黃埔]

[row:lisi_1495527850136],[family:address],[qualifier:province],[value:shanghai]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21]

[row:lisi_1495527850154],[family:info],[qualifier:sex],[value:女]

[row:lisi_1495527850159],[family:userid],[qualifier:id],[value:002]

[row:wangwu_1495595824517],[family:userid],[qualifier:id],[value:009]

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646]

[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china]

[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan]

[row:zhangsan_1495527850951],[family:address],[qualifier:province],[value:guangdong]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100]

[row:zhangsan_1495527851080],[family:info],[qualifier:sex],[value:男]

[row:zhangsan_1495527851095],[family:userid],[qualifier:id],[value:001]

 

7. FirstKeyOnlyFilter

該過濾器僅僅返回每一行中的第一個cell的值,可以用於高效的執行行數統計操作。

構造函數:

public FirstKeyOnlyFilter()

代碼:

Table table = connection.getTable(TableName.valueOf("user"));

FirstKeyOnlyFilter fkof = new FirstKeyOnlyFilter();

Scan scan = new Scan();

scan.setFilter(fkof);

ResultScanner rs = table.getScanner(scan);

結果:

[row:lisi_1495527849910],[family:account],[qualifier:idcard],[value:42963319861234561230],[time:1495556647872]

[row:lisi_1495527850081],[family:account],[qualifier:name],[value:lisi],[time:1495556647984]

[row:lisi_1495527850111],[family:account],[qualifier:password],[value:123451231236],[time:1495556648013]

[row:lisi_1495527850114],[family:address],[qualifier:city],[value:黃埔],[time:1495556648017]

[row:lisi_1495527850136],[family:address],[qualifier:province],[value:shanghai],[time:1495556648041]

[row:lisi_1495527850144],[family:info],[qualifier:age],[value:21],[time:1495556648045]

[row:lisi_1495527850154],[family:info],[qualifier:sex],[value:女],[time:1495556648056]

[row:lisi_1495527850159],[family:userid],[qualifier:id],[value:002],[time:1495556648060]

[row:wangwu_1495595824517],[family:userid],[qualifier:id],[value:009],[time:1495624624131]

[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]

[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]

[row:zhangsan_1495527850951],[family:address],[qualifier:province],[value:guangdong],[time:1495556648855]

[row:zhangsan_1495527850975],[family:info],[qualifier:age],[value:100],[time:1495556648878]

[row:zhangsan_1495527851080],[family:info],[qualifier:sex],[value:男],[time:1495556648983]

[row:zhangsan_1495527851095],[family:userid],[qualifier:id],[value:001],[time:1495556648996]

看着返回數據還沒明白,僅僅返回每一行中的第一個cell的值,可以用於高效的執行行數統計操作。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章