HBase(0.96以上版本)過濾器Filter詳解及例項程式碼
引言 -- 引數基礎
有兩個引數類在各類Filter中經常出現,統一介紹下:
(1)比較運算子 CompareFilter.CompareOp
比較運算子用於定義比較關係,可以有以下幾類值供選擇:
- EQUAL 相等
- GREATER 大於
- GREATER_OR_EQUAL 大於等於
- LESS 小於
- LESS_OR_EQUAL 小於等於
- NOT_EQUAL 不等於
(2)比較器 ByteArrayComparable
通過比較器可以實現多樣化目標匹配效果,比較器有以下子類可以使用:
- BinaryComparator
匹配完整位元組陣列 - BinaryPrefixComparator 匹配位元組陣列字首
- BitComparator
- NullComparator
- RegexStringComparator 正規表示式匹配
- SubstringComparator 子串匹配
1.
結構(Structural)過濾器--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)。
(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)
2.1.第一種建構函式情況
-- 比較的關鍵字是字元陣列
官網示例程式碼,檢查列值和字串'my
value' 相等:
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
Bytes.toBytes("my value")
);
scan.setFilter(filter);
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
Bytes.toBytes("2013-06-08")
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
注意:還是大寫問題,HBase的列名必須大寫!
2.2.第二種建構函式情況 -- 比較的關鍵字是比較器ByteArrayComparable
該章節主要是針對SingleColumnValueFilter的第二種建構函式使用情況做了一些舉例:
(1)支援值比較的正規表示式 -- RegexStringComparator
官網示例程式碼:
RegexStringComparator comp = new RegexStringComparator("my.");
//任意以my打頭的值
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
comp
);
scan.setFilter(filter);
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
RegexStringComparator comp = new RegexStringComparator("2013-06-1.");
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
comp
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
(2)檢測一個子串是否存在於值中(大小寫不敏感)
-- SubstringComparator
官網示例程式碼:
SubstringComparator comp = new SubstringComparator("y val"); //
looking for 'my value'
SingleColumnValueFilter filter = new SingleColumnValueFilter(
cf,
column,
CompareOp.EQUAL,
comp
);
scan.setFilter(filter);
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
// RegexStringComparator comp = new RegexStringComparator("2013-06-1.");
SubstringComparator comp = new SubstringComparator("2013-06-1");
SingleColumnValueFilter filter = new SingleColumnValueFilter(
Bytes.toBytes("patentinfo"),
Bytes.toBytes("CREATE_TIME"),
CompareOp.EQUAL,
comp
);
filterList.addFilter(filter);
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
System.out.println("Scan: " + r);
}
table.close();
(3)BinaryComparator
二進位制比較器,用得較少,有需要請自行查閱官網:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryComparator.html
(4)BinaryPrefixComparator
二進位制字首比較器,用得較少,有需要請自行查閱官網:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.html
3. 鍵值後設資料
由於HBase 採用鍵值對儲存內部資料,鍵值後設資料過濾器評估一行的鍵(ColumnFamily:Qualifiers)是否存在 ,
對應前節所述值的情況。
對應前節所述值的情況。
3.1. 基於列族過濾資料的FamilyFilter
建構函式:
FamilyFilter(CompareFilter.CompareOp familyCompareOp, ByteArrayComparable familyComparator)
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* FamilyFilter建構函式中第二個引數是ByteArrayComparable型別
* ByteArrayComparable類參見“引言-引數基礎”章節
* 下面僅以最可能用到的BinaryComparator、BinaryPrefixComparator舉例:
*/
FamilyFilter ff = new FamilyFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("pat")) //表中不存在pat列族,過濾結果為空
);
FamilyFilter ff1 = new FamilyFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("pat")) //表中存在以pat打頭的列族patentinfo,過濾結果為該列族所有行
);
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
注意:
- 如果希望查詢的是一個已知的列族,則使用 scan.addFamily(family) 比使用過濾器效率更高;
- 由於目前HBase對多列族支援不完善,所以該過濾器目前用途不大。
3.2. 基於限定符Qualifier(列)過濾資料的QualifierFilter
建構函式:
QualifierFilter(CompareFilter.CompareOp op, ByteArrayComparable qualifierComparator)
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* QualifierFilter建構函式中第二個引數是ByteArrayComparable型別
* ByteArrayComparable類有以下子類可以使用:
* *******************************************
* BinaryComparator 匹配完整位元組陣列,
* BinaryPrefixComparator 匹配開始的部分位元組陣列,
* BitComparator,
* NullComparator,
* RegexStringComparator, 正規表示式匹配
* SubstringComparator
* *******************************************
* 下面僅以最可能用到的BinaryComparator、BinaryPrefixComparator舉例:
*/
QualifierFilter ff = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("belong")) //表中不存在belong列,過濾結果為空
);
QualifierFilter ff1 = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("BELONG")) //表中存在以BELONG打頭的列BELONG_SITE,過濾結果為所有行的該列資料
);
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
說明:
- 一旦涉及到列(Qualifier),HBase就只認大寫字母了!
- 該過濾器應該比FamilyFilter更常用!
3.3. 基於列名(即Qualifier)字首過濾資料的ColumnPrefixFilter
( 該功能用QualifierFilter也能實現 )
( 該功能用QualifierFilter也能實現 )
建構函式:
ColumnPrefixFilter(byte[] prefix)
注意:
一個列名是可以出現在多個列族中的,該過濾器將返回所有列族中匹配的列。
官網示例程式碼,查詢所有"abc"打頭的列:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[] prefix = Bytes.toBytes("abc");
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new ColumnPrefixFilter(prefix);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
//返回所有行中以BELONG打頭的列的資料
ColumnPrefixFilter ff1 = new ColumnPrefixFilter(Bytes.toBytes("BELONG"));
Scan scan = new Scan();
scan.setFilter(ff1);
ResultScanner rs = table.getScanner(scan);
3.4. 基於多個列名(即Qualifier)字首過濾資料的MultipleColumnPrefixFilter
說明:
MultipleColumnPrefixFilter 和 ColumnPrefixFilter 行為差不多,但可以指定多個字首。
官方示例程式碼,查詢所有"abc"或"xyz"打頭的列:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[][] prefixes = new byte[][] {Bytes.toBytes("abc"), Bytes.toBytes("xyz")};
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new MultipleColumnPrefixFilter(prefixes);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
byte[][] prefixes = new byte[][] {Bytes.toBytes("BELONG"), Bytes.toBytes("CREATE")};
//返回所有行中以BELONG或者CREATE打頭的列的資料
MultipleColumnPrefixFilter ff = new MultipleColumnPrefixFilter(prefixes);
Scan scan = new Scan();
scan.setFilter(ff);
ResultScanner rs = table.getScanner(scan);
3.5. 基於列範圍(不是行範圍)過濾資料ColumnRangeFilter
說明:
- 可用於獲得一個範圍的列,例如,如果你的一行中有百萬個列,但是你只希望檢視列名為bbbb到dddd的範圍
- 該方法從 HBase 0.92 版本開始引入
- 一個列名是可以出現在多個列族中的,該過濾器將返回所有列族中匹配的列
建構函式:
ColumnRangeFilter(byte[] minColumn, boolean minColumnInclusive, byte[] maxColumn, boolean maxColumnInclusive)
引數解釋:
- minColumn - 列範圍的最小值,如果為空,則沒有下限;
- minColumnInclusive - 列範圍是否包含minColumn ;
- maxColumn - 列範圍最大值,如果為空,則沒有上限;
- maxColumnInclusive - 列範圍是否包含maxColumn 。
官網示例程式碼,查詢列名在"bbbb"到"dddd"範圍的資料:
HTableInterface t = ...;
byte[] row = ...;
byte[] family = ...;
byte[] startColumn = Bytes.toBytes("bbbb");
byte[] endColumn = Bytes.toBytes("bbdd");
Scan scan = new Scan(row, row); // (optional) limit to one row
scan.addFamily(family); // (optional) limit to one family
Filter f = new ColumnRangeFilter(startColumn, true, endColumn, true);
scan.setFilter(f);
scan.setBatch(10); // set this if there could be many columns returned
ResultScanner rs = t.getScanner(scan);
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
rs.close();
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
byte[] startColumn = Bytes.toBytes("C");
byte[] endColumn = Bytes.toBytes("D");
//返回所有列中從C到D打頭的範圍的資料,實際返回類似CREATOR、CREATE_TIME、CHANNEL_CODE等列的資料
ColumnRangeFilter ff = new ColumnRangeFilter(startColumn, true, endColumn, true);
Scan scan = new Scan();
scan.setFilter(ff);
ResultScanner rs = table.getScanner(scan);
4.
RowKey
當需要根據行鍵特徵查詢一個範圍的行資料時,使用Scan的startRow和stopRow會更高效,但是,startRow和stopRow只能匹配行鍵的開始字元,而不能匹配中間包含的字元:
byte[] startColumn = Bytes.toBytes("aaa");
byte[] endColumn = Bytes.toBytes("bbb");
Scan scan = new Scan(startColumn,endColumn);
當需要針對行鍵進行更復雜的過濾時,可以使用RowFilter:
建構函式:
RowFilter(CompareFilter.CompareOp rowCompareOp, ByteArrayComparable rowComparator)
引數解釋參見“引言-引數基礎”章節。
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
/**
* rowkey格式為:建立日期_釋出日期_ID_TITLE
* 目標:查詢 釋出日期 為 2013-07-16 的資料
*/
RowFilter rf = new RowFilter(
CompareFilter.CompareOp.EQUAL ,
new SubstringComparator("_2013-07-16_")
);
Scan scan = new Scan();
scan.setFilter(rf);
ResultScanner rs = table.getScanner(scan);
注意:
測試過程中嘗試通過組合使用兩個RowFilter(CompareFilter.CompareOp引數分別為GREATER_OR_EQUAL和LESS_OR_EQUAL),和SubstringComparator,過濾找出指定釋出時間範圍內的資料,但結果比較意外,不是預想的資料,估計比較運算子GREATER_OR_EQUAL和LESS_OR_EQUAL和比較器SubstringComparator組合使用效果不太好,慎用。
5.PageFilter
指定頁面行數,返回對應行數的結果集。
需要注意的是,該過濾器並不能保證返回的結果行數小於等於指定的頁面行數,因為過濾器是分別作用到各個region server的,它只能保證當前region返回的結果行數不超過指定頁面行數。
建構函式:
PageFilter(long pageSize)
實測程式碼(從“2013-07-26”行開始,取5行):
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("2013-07-26"));
PageFilter pf = new PageFilter(5L);
scan.setFilter(pf);
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
注意:
由於該過濾器並不能保證返回的結果行數小於等於指定的頁面行數,所以更好的返回指定行數的辦法是ResultScanner.next(int
nbRows) ,即:
nbRows) ,即:
ResultScanner rs = table.getScanner(scan);
for (Result r : rs.next(5)) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
6.SkipFilter
根據整行中的每個列來做過濾,只要存在一列不滿足條件,整行都被過濾掉。
例如,如果一行中的所有列代表的是不同物品的重量,則真實場景下這些數值都必須大於零,我們希望將那些包含任意列值為0的行都過濾掉。
在這個情況下,我們結合ValueFilter和SkipFilter共同實現該目的:
scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,new BinaryComparator(Bytes.toBytes(0))));
建構函式:
SkipFilter(Filter filter)
個人實測程式碼:
目前的資料:
hbase(main):009:0> scan 'rd_ns:itable'
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405417403438, value=anywhere
100001 column=info:age, timestamp=1405417403438, value=24
100001 column=info:name, timestamp=1405417403438, value=zhangtao
100002 column=info:address, timestamp=1405417426693, value=shangdi
100002 column=info:age, timestamp=1405417426693, value=28
100002 column=info:name, timestamp=1405417426693, value=shichao
100003 column=info:address, timestamp=1405494141522, value=huilongguan
100003 column=info:age, timestamp=1405494999631, value=29
100003 column=info:name, timestamp=1405494141522, value=liyang
3 row(s) in 0.0190 seconds
執行以下程式碼:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "rd_ns:itable");
Scan scan = new Scan();
scan.setFilter(new SkipFilter(new ValueFilter(CompareOp.NOT_EQUAL,
new BinaryComparator(Bytes.toBytes("28")))));
ResultScanner rs = table.getScanner(scan);
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println("Rowkey : " + Bytes.toString(r.getRow())
+ " Familiy:Quilifier : "
+ Bytes.toString(CellUtil.cloneQualifier(cell))
+ " Value : "
+ Bytes.toString(CellUtil.cloneValue(cell))
+ " Time : " + cell.getTimestamp());
}
}
table.close();
輸出結果(整個100002行被過濾掉了):
Rowkey : 100001 Familiy:Quilifier : address Value : anywhere Time : 1405417403438
Rowkey : 100001 Familiy:Quilifier : age Value : 24 Time : 1405417403438
Rowkey : 100001 Familiy:Quilifier : name Value : zhangtao Time : 1405417403438
Rowkey : 100003 Familiy:Quilifier : address Value : huilongguan Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : age Value : 29 Time : 1405494999631
Rowkey : 100003 Familiy:Quilifier : name Value : liyang Time : 1405494141522
7.
Utility--FirstKeyOnlyFilter
該過濾器僅僅返回每一行中的第一個cell的值,可以用於高效的執行行數統計操作。
估計實戰意義不大。
建構函式:
public FirstKeyOnlyFilter()
個人實測程式碼:
HTable table = HBaseDAO.getHTable("147patents");
FirstKeyOnlyFilter fkof = new FirstKeyOnlyFilter();
Scan scan = new Scan();
scan.setFilter(fkof);
ResultScanner rs = table.getScanner(scan);
8.
取得查詢結果
無論是官網的Ref Guide還是網上流傳的大部分部落格中,輸出查詢結果的程式碼都是:
for (Result r = rs.next(); r != null; r = rs.next()) {
for (KeyValue kv : r.raw()) {
// each kv represents a column
}
}
但檢視最新的API可知Result例項的raw()方法已經不建議使用了:
raw() Deprecated. as
of 0.96, use rawCells()
0.96以後版本正確的獲取結果程式碼如下:
for (Result r : rs) {
for (Cell cell : r.rawCells()) {
System.out.println(
"Rowkey : "+Bytes.toString(r.getRow())+
"Familiy:Quilifier : "+Bytes.toString(CellUtil.cloneQualifier(cell))+
"Value : "+Bytes.toString(CellUtil.cloneValue(cell))
);
}
}
作者: creditor http://www.xuebuyuan.com/2046843.html
相關文章
- HBase Filter 過濾器之 ValueFilter 詳解Filter過濾器
- 布隆過濾器(Bloom Filter)詳解過濾器OOMFilter
- Filter(過濾器)與Listener(監聽器)詳解Filter過濾器
- Filter過濾器Filter過濾器
- hbase過濾器過濾器
- 好程式設計師大資料培訓分享HBase Filter過濾器概述程式設計師大資料Filter過濾器
- PHP 過濾器(Filter)PHP過濾器Filter
- MySQL 序列 AUTO_INCREMENT詳解及例項程式碼MySqlREM
- 使用Filter介面編寫過濾器解決post亂碼Filter過濾器
- JavaWeb 中 Filter過濾器JavaWebFilter過濾器
- Filter過濾器的使用Filter過濾器
- filter過濾Filter
- 布隆過濾器(Bloom Filter)過濾器OOMFilter
- 布隆過濾器 Bloom Filter過濾器OOMFilter
- Bloom Filter 布隆過濾器OOMFilter過濾器
- 攔截器(Interceptor)與過濾器(Filter)過濾器Filter
- 微信小程式 使用filter過濾器幾種方式微信小程式Filter過濾器
- EventBus詳解及簡單例項單例
- 如何在vue中使用過濾器filterVue過濾器Filter
- Vue定義全域性過濾器filterVue過濾器Filter
- Python訪問小程式簡單方法程式碼例項詳解Python
- SpringBoot系列(十二)過濾器配置詳解Spring Boot過濾器
- 詳解卡爾曼濾波(Kalman Filter)原理Filter
- 滑動視窗濾波器原理分析及詳細程式碼講解實現
- Oracle minus用法詳解及應用例項Oracle
- 例項程式碼詳解正規表示式匹配換行
- LINUX Shell指令碼程式設計例項詳解(一)上Linux指令碼程式設計
- 合成複用原則詳解篇(附圖解及原始碼例項)圖解原始碼
- Tomcat常見異常及解決方案程式碼例項Tomcat
- 4、過濾器的使用及自定義過濾器過濾器
- 過濾器 Filter 與 攔截器 Interceptor 的區別過濾器Filter
- JavaWeb - 【Filter】敏感詞過濾JavaWebFilter
- Elasticsearch——filter過濾查詢ElasticsearchFilter
- ubuntu ftp 伺服器搭建及vsftpd.conf配置例項詳解UbuntuFTP伺服器
- Fabric 1.0原始碼分析(11)consenter(共識外掛) #filter(過濾器)原始碼Filter過濾器
- Linux IO模式及 select、poll、epoll詳解(含部分例項原始碼)Linux模式原始碼
- Redis詳解(十三)------ Redis布隆過濾器Redis過濾器
- SpringBoot+Shiro學習(七):Filter過濾器管理Spring BootFilter過濾器
- CSS3 Flex 彈性佈局例項程式碼詳解CSSS3Flex