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...