關於hbase過濾查詢的一些

2021-07-30 11:08:24 字數 3714 閱讀 2124

hbase有兩種查詢的方式乙個get  乙個scan

其中get是根據精確的rowkey查出單條的記錄    ,那麼如果一條記錄是有成千上萬個字段的話,網路io大,所以要

get.addcolumn(bytes.tobytes("cf"), bytes.tobytes("f3"));

get.addcolumn(bytes.tobytes("cf"), bytes.tobytes("f2"));

來新增和指定要返回的字段

還有一種方式是get.setfilter(filter)   ,這個我沒試過

scan 自然也有按照filter來篩選出要返回的字段

filter是這樣,客戶端可以把filter傳送到各個regionserver中,做到在服務端去過濾,從而減少網路io,而不是說乙個簡單的scan把所有符合rowkey的都返回給客戶端,由客戶端來做過濾處理。

如果是get的filter只能做針對列的過濾的話

scan的filter既有針對rowkey的過濾也有針對列的過濾,從而形成乙個行列的聚焦。

針對rowkey的filter 用的最多的是字首過濾

prefixfilter prefixfilter = new prefixfilter(bytes.tobytes("01_1893300"));  

這裡要多說一句,這裡字首實際的所用是包含  也就是說    01_1893300_aa   和  aa_01_1893300 都是符合字首過濾的

針對列過濾的我這裡常用的是列名的filter ,如果要返回多個列的話

qualifierfilter qualifierfilter1 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f1")));

qualifierfilter qualifierfilter2 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f2")));

當scan既要對行也要對列進行同時過濾時,要用filterlist來整合

但這時要注意,filterlist只能用來整合列的,不要把列過濾和行過濾都一起整合到filterlist

例如這裡就是

//先建立乙個scan

scan scan = new scan();  

//建立了乙個rowkey字首過濾

prefixfilter prefixfilter = new prefixfilter(bytes.tobytes("01_1893300"));   

//直接把filter設定到scan中(單獨設定)

scan.setfilter(prefixfilter);   

//建立乙個fliterlist    (operator.must_pass_one,operator.must_pass_all)

filterlist filterlist = new filterlist(operator.must_pass_one);   //要是兩個列都含有的話,一定要設定為one

//建立兩個列過濾

qualifierfilter qualifierfilter1 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f1")));

qualifierfilter qualifierfilter2 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f2")));

//把兩個列過濾放到filterlist中而不要把rowkey行過濾放入

filterlist.addfilter(qualifierfilter1);

filterlist.addfilter(qualifierfilter2);

//把這個filterlist設定到scan中

scan.setfilter(filterlist);   

這樣才會過濾下來你指定的行 和 指定的列的值,其他的都不會通過網路傳到客戶端了

另外hbase是設計成按照rowkey來查詢才能最大化查詢效率的,我沒有用過二級索引,所以就不說這個了

那麼如果單通過列值來過濾話就會效果很差

還有如果通過filter查到了也就罷了,如果filter後查不到,響應速度就會很慢,會有十幾秒

所以當用filter時要加個判斷

if (result.getvalue(bytes.tobytes("cf"), bytes.tobytes("f2")) != null)

那麼分別給個get  和  scan  的帶過濾的查詢的列子

//table table = hbaseutils.gethtable();

//get get = new get(bytes.tobytes("01_1893300_aa"));

get.setfilter(filter)

//"cf"), bytes.tobytes("f3"));

"cf"), bytes.tobytes("f2"));

////result result = table.get(get);

//"cf"), bytes.tobytes("f1"))));  // result.getrow()  是獲得rowkey

//-------------------------

table table = hbaseutils.gethtable();

scan scan = new scan();  

filterlist filterlist = new filterlist(operator.must_pass_one);

prefixfilter prefixfilter = new prefixfilter(bytes.tobytes("01_1893300"));    //字首的話  ,其實不在字首也是可以的

qualifierfilter qualifierfilter1 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f1")));

qualifierfilter qualifierfilter2 = new qualifierfilter(compareop.equal, new binarycomparator(bytes.tobytes("f2")));

filterlist.addfilter(qualifierfilter1);

filterlist.addfilter(qualifierfilter2);

scan.setfilter(prefixfilter);   

scan.setfilter(filterlist);   

resultscanner scanner = table.getscanner(scan);  

for (result result : scanner)

// 判斷取出來的值是否為空

if (result.getvalue(bytes.tobytes("cf"), bytes.tobytes("f3")) != null)

}最後多說一句 以手機號為例  183**********

如果hbase的業務偏向查詢的話,那手機號最好正寫,當批量查詢是會從同乙個region出,效率高

如果hbase的業務偏向插入的話,那手機號最好反寫,當批量插入的時候,寫時分布平衡

參考

關於HBase擴容的一些思考

參考 hbase在滴滴的應用場景和最佳實踐 一是說新增的rs節點的配置最好要和前面的一致 在此以後,進行region的遷移,hbase與balance的命令,在這裡不建議使用自動的balance,因為balance主要的問題是不會根據表來進行balance,hbase的balance只會根據rs的上...

一些簡單的hbase語法

建立namespace mydemo 相當於建立乙個資料庫 create namespace mydemo 在namespace中建立乙個表 userinfos 表中有乙個列簇 base create mydemo.userinfos base 檢視所有表名 list 在列簇中插入資料 put my...

關於連線查詢的一些看法

正確的 select a.name,a.stuno,sum b.score from student a score b where a.stuno b.stuno and b.stuno 2 group by a.name,a.stuno select a.name,a.stuno,sum b.s...