HBase簡(jiǎn)介
HBase是一個(gè)分布式的、面向列的開(kāi)源數(shù)據(jù)庫(kù),該技術(shù)來(lái)源于 Fay Chang 所撰寫(xiě)的Google論文“Bigtable:一個(gè)結(jié)構(gòu)化數(shù)據(jù)的分布式存儲(chǔ)系統(tǒng)”。就像Bigtable利用了Google文件系統(tǒng)(File System)所提供的分布式數(shù)據(jù)存儲(chǔ)一樣,HBase在Hadoop之上提供了類(lèi)似于Bigtable的能力。HBase是Apache的Hadoop項(xiàng)目的子項(xiàng)目。HBase不同于一般的關(guān)系數(shù)據(jù)庫(kù),它是一個(gè)適合于非結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)庫(kù)。另一個(gè)不同的是HBase基于列的而不是基于行的模式。
什么時(shí)候需要HBase呢?
半結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù),對(duì)于數(shù)據(jù)結(jié)構(gòu)字段不夠確定或雜亂無(wú)章很難按一個(gè)概念去進(jìn)行抽取的數(shù)據(jù)適合用HBase。當(dāng)業(yè)務(wù)發(fā)展需要存儲(chǔ)author的email,phone,address信息時(shí)RDBMS需要停機(jī)維護(hù),而HBase支持動(dòng)態(tài)增加。
記錄非常稀疏
RDBMS的行有多少列是固定的,為null的列浪費(fèi)了存儲(chǔ)空間。而如上文提到的,HBase為null的Column不會(huì)被存儲(chǔ),這樣既節(jié)省了空間又提高了讀性能。
多版本數(shù)據(jù)
如上文提到的根據(jù)Row key和Column key定位到的Value可以有任意數(shù)量的版本值,因此對(duì)于需要存儲(chǔ)變動(dòng)歷史記錄的數(shù)據(jù),用HBase就非常方便了。比如上例中的author的Address是會(huì)變動(dòng)的,業(yè)務(wù)上一般只需要最新的值,但有時(shí)可能需要查詢(xún)到歷史值。
超大數(shù)據(jù)量
當(dāng)數(shù)據(jù)量越來(lái)越大,RDBMS數(shù)據(jù)庫(kù)撐不住了,就出現(xiàn)了讀寫(xiě)分離策略,通過(guò)一個(gè)Master專(zhuān)門(mén)負(fù)責(zé)寫(xiě)操作,多個(gè)Slave負(fù)責(zé)讀操作,服務(wù)器成本倍增。隨著壓力增加,Master撐不住了,這時(shí)就要分庫(kù)了,把關(guān)聯(lián)不大的數(shù)據(jù)分開(kāi)部署,一些join查詢(xún)不能用了,需要借助中間層。隨著數(shù)據(jù)量的進(jìn)一步增加,一個(gè)表的記錄越來(lái)越大,查詢(xún)就變得很慢,于是又得搞分表,比如按ID取模分成多個(gè)表以減少單個(gè)表的記錄數(shù)。經(jīng)歷過(guò)這些事的人都知道過(guò)程是多么的折騰。采用HBase就簡(jiǎn)單了,只需要加機(jī)器即可,HBase會(huì)自動(dòng)水平切分?jǐn)U展,跟Hadoop的無(wú)縫集成保障了其數(shù)據(jù)可靠性(HDFS)和海量數(shù)據(jù)分析的高性能(MapReduce)。
HTable一些基本概念
Row key
行主鍵, HBase不支持條件查詢(xún)和Order by等查詢(xún),讀取記錄只能按Row key(及其range)或全表掃描,因此Row key需要根據(jù)業(yè)務(wù)來(lái)設(shè)計(jì)以利用其存儲(chǔ)排序特性(Table按Row key字典序排序如1,10,100,11,2)提高性能。
Column Family(列族)
在表創(chuàng)建時(shí)聲明,每個(gè)Column Family為一個(gè)存儲(chǔ)單元。在上例中設(shè)計(jì)了一個(gè)HBase表blog,該表有兩個(gè)列族:article和author。
Column(列)
HBase的每個(gè)列都屬于一個(gè)列族,以列族名為前綴,如列article:title和article:content屬于article列族,author:name和author:nickname屬于author列族。
Column不用創(chuàng)建表時(shí)定義即可以動(dòng)態(tài)新增,同一Column Family的Columns會(huì)群聚在一個(gè)存儲(chǔ)單元上,并依Column key排序,因此設(shè)計(jì)時(shí)應(yīng)將具有相同I/O特性的Column設(shè)計(jì)在一個(gè)Column Family上以提高性能。
Timestamp
HBase通過(guò)row和column確定一份數(shù)據(jù),這份數(shù)據(jù)的值可能有多個(gè)版本,不同版本的值按照時(shí)間倒序排序,即最新的數(shù)據(jù)排在最前面,查詢(xún)時(shí)默認(rèn)返回最新版本。如上例中row key=1的author:nickname值有兩個(gè)版本,分別為1317180070811對(duì)應(yīng)的“一葉渡江”和1317180718830對(duì)應(yīng)的“yedu”(對(duì)應(yīng)到實(shí)際業(yè)務(wù)可以理解為在某時(shí)刻修改了nickname為yedu,但舊值仍然存在)。Timestamp默認(rèn)為系統(tǒng)當(dāng)前時(shí)間(精確到毫秒),也可以在寫(xiě)入數(shù)據(jù)時(shí)指定該值。
Value
每個(gè)值通過(guò)4個(gè)鍵唯一索引,tableName+RowKey+ColumnKey+Timestamp=》value,例如上例中{tableName=’blog’,RowKey=’1’,ColumnName=’author:nickname’,Timestamp=’ 1317180718830’}索引到的唯一值是“yedu”。
存儲(chǔ)類(lèi)型
TableName 是字符串
RowKey 和 ColumnName 是二進(jìn)制值(Java 類(lèi)型 byte[])
Timestamp 是一個(gè) 64 位整數(shù)(Java 類(lèi)型 long)
value 是一個(gè)字節(jié)數(shù)組(Java類(lèi)型 byte[])。
將HTable的存儲(chǔ)結(jié)構(gòu)理解為
即HTable按Row key自動(dòng)排序,每個(gè)Row包含任意數(shù)量個(gè)Columns,Columns之間按Column key自動(dòng)排序,每個(gè)Column包含任意數(shù)量個(gè)Values。理解該存儲(chǔ)結(jié)構(gòu)將有助于查詢(xún)結(jié)果的迭代。
HTable使用教程
對(duì)于建表,和RDBMS類(lèi)似,HBase也有namespace的概念,可以指定表空間創(chuàng)建表,也可以直接創(chuàng)建表,進(jìn)入default表空間。
對(duì)于數(shù)據(jù)操作,HBase支持四類(lèi)主要的數(shù)據(jù)操作,分別是:
· Put:增加一行,修改一行;
· Delete:刪除一行,刪除指定列族,刪除指定column的多個(gè)版本,刪除指定column的制定版本等;
· Get:獲取指定行的所有信息,獲取指定行和指定列族的所有colunm,獲取指定column,獲取指定column的幾個(gè)版本,獲取指定column的指定版本等;
· Scan:獲取所有行,獲取指定行鍵范圍的行,獲取從某行開(kāi)始的幾行,獲取滿(mǎn)足過(guò)濾條件的行等。
這四個(gè)類(lèi)都是org.apache.hadoop.hbase.client的子類(lèi),可以到官網(wǎng)API去查看詳細(xì)信息,本文僅總結(jié)常用方法,力爭(zhēng)讓讀者用20%的時(shí)間掌握80%的常用功能。
1. 命名空間Namespace
在關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)中,命名空間namespace指的是一個(gè)表的邏輯分組,同一組中的表有類(lèi)似的用途。命名空間的概念為即將到來(lái)的多租戶(hù)特性打下基礎(chǔ):
· 配額管理(Quota Management (HBASE-8410)):限制一個(gè)namespace可以使用的資源,資源包括region和table等;
· 命名空間安全管理(Namespace Security Administration (HBASE-9206)):提供了另一個(gè)層面的多租戶(hù)安全管理;
· Region服務(wù)器組(Region server groups (HBASE-6721)):一個(gè)命名空間或一張表,可以被固定到一組regionservers上,從而保證了數(shù)據(jù)隔離性。
1.1.命名空間管理
命名空間可以被創(chuàng)建、移除、修改。
表和命名空間的隸屬關(guān)系在在創(chuàng)建表時(shí)決定,通過(guò)以下格式指定:
《namespace》:《table》
Example:hbase shell中創(chuàng)建命名空間、創(chuàng)建命名空間中的表、移除命名空間、修改命名空間
?
1.2. 預(yù)定義的命名空間
有兩個(gè)系統(tǒng)內(nèi)置的預(yù)定義命名空間:
· hbase:系統(tǒng)命名空間,用于包含hbase的內(nèi)部表
· default:所有未指定命名空間的表都自動(dòng)進(jìn)入該命名空間
Example:指定命名空間和默認(rèn)命名空間
#namespace=foo and table qualifier=bar
create ‘foo:bar’, ‘fam’
#namespace=default and table qualifier=bar
create ‘bar’, ‘fam’
2. 創(chuàng)建表
廢話(huà)不多說(shuō),直接上樣板代碼,代碼后再說(shuō)明注意事項(xiàng)和知識(shí)點(diǎn):
關(guān)鍵知識(shí)點(diǎn):
必須將HBase集群的hbase-site.xml文件添加進(jìn)工程的classpath中,或者通過(guò)Configuration對(duì)象設(shè)置相關(guān)屬性,否則程序獲取不到集群相關(guān)信息,也就無(wú)法找到集群,運(yùn)行程序時(shí)會(huì)報(bào)錯(cuò);
HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(“my_ns:mytable”))代碼是描述表mytable,并將mytable放到了my_ns命名空間中,前提是該命名空間已存在,如果指定的是不存在命名空間,則會(huì)報(bào)錯(cuò)org.apache.hadoop.hbase.NamespaceNotFoundException;
命名空間一般在建模階段通過(guò)命令行創(chuàng)建,在java代碼中通過(guò)admin.createNamespace(NamespaceDescriptor.create(“my_ns”).build())創(chuàng)建的機(jī)會(huì)不多;
創(chuàng)建HBaseAdmin對(duì)象時(shí)就已經(jīng)建立了客戶(hù)端程序與HBase集群的connection,所以在程序執(zhí)行完成后,務(wù)必通過(guò)admin.close()關(guān)閉connection;
可以通過(guò)HTableDescriptor對(duì)象設(shè)置表的特性,比如:通過(guò)tableDesc.setMaxFileSize(512)設(shè)置一個(gè)region中的store文件的最大size,當(dāng)一個(gè)region中的最大store文件達(dá)到這個(gè)size時(shí),region就開(kāi)始分裂;通過(guò)tableDesc.setMemStoreFlushSize(512)設(shè)置region內(nèi)存中的memstore的最大值,當(dāng)memstore達(dá)到這個(gè)值時(shí),開(kāi)始往磁盤(pán)中刷數(shù)據(jù)。更多特性請(qǐng)自行查閱官網(wǎng)API;
可以通過(guò)HColumnDescriptor對(duì)象設(shè)置列族的特性,比如:通過(guò)hcd.setTimeToLive(5184000)設(shè)置數(shù)據(jù)保存的最長(zhǎng)時(shí)間;通過(guò)hcd.setInMemory(true)設(shè)置數(shù)據(jù)保存在內(nèi)存中以提高響應(yīng)速度;通過(guò) hcd.setMaxVersions(10)設(shè)置數(shù)據(jù)保存的最大版本數(shù);通過(guò)hcd.setMinVersions(5)設(shè)置數(shù)據(jù)保存的最小版本數(shù)(配合TimeToLive使用)。更多特性請(qǐng)自行查閱官網(wǎng)API;
數(shù)據(jù)的版本數(shù)只能通過(guò)HColumnDescriptor對(duì)象設(shè)置,不能通過(guò)HTableDescriptor對(duì)象設(shè)置;
由于HBase的數(shù)據(jù)是先寫(xiě)入內(nèi)存,數(shù)據(jù)累計(jì)達(dá)到內(nèi)存閥值時(shí)才往磁盤(pán)中flush數(shù)據(jù),所以,如果在數(shù)據(jù)還沒(méi)有flush進(jìn)硬盤(pán)時(shí),regionserver down掉了,內(nèi)存中的數(shù)據(jù)將丟失。要想解決這個(gè)場(chǎng)景的問(wèn)題就需要用到WAL(Write-Ahead-Log),tableDesc.setDurability(Durability.SYNC_WAL)就是設(shè)置寫(xiě)WAL日志的級(jí)別,示例中設(shè)置的是同步寫(xiě)WAL,該方式安全性較高,但無(wú)疑會(huì)一定程度影響性能,請(qǐng)根據(jù)具體場(chǎng)景選擇使用;
setDurability(Durability d)方法可以在相關(guān)的三個(gè)對(duì)象中使用,分別是:HTableDescriptor,Delete,Put(其中Delete和Put的該方法都是繼承自父類(lèi)org.apache.hadoop.hbase.client.Mutation)。分別針對(duì)表、插入操作、刪除操作設(shè)定WAL日志寫(xiě)入級(jí)別。需要注意的是,Delete和Put并不會(huì)繼承Table的Durability級(jí)別(已實(shí)測(cè)驗(yàn)證)。Durability是一個(gè)枚舉變量,可選值參見(jiàn)4.2節(jié)。如果不通過(guò)該方法指定WAL日志級(jí)別,則為默認(rèn)USE_DEFAULT級(jí)別。
3.刪除表
刪除表沒(méi)創(chuàng)建表那么多學(xué)問(wèn),直接上代碼:
?
4、修改表
4.1.實(shí)例代碼
(1)刪除列族、新增列族
修改之前,四個(gè)列族:
hbase(main):014:0》 describe ‘rd_ns:itable’
DESCRIPTION ENABLED
‘rd_ns:itable’, {NAME =》 ‘info’, DATA_BLOCK_ENCODING =》 ‘NONE’, BLOOMFILTER =》 ‘ROW’, REPLICATION_SCOPE =》 ‘0’, V true
ERSIONS =》 ‘10’, COMPRESSION =》 ‘NONE’, MIN_VERSIONS =》 ‘0’, TTL =》 ‘2147483647’, KEEP_DELETED_CELLS =》 ‘false’,
BLOCKSIZE =》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》 ‘true’}, {NAME =》 ‘newcf’, DATA_BLOCK_ENCODING =》 ‘NONE
’, BLOOMFILTER =》 ‘ROW’, REPLICATION_SCOPE =》 ‘0’, COMPRESSION =》 ‘NONE’, VERSIONS =》 ‘10’, TTL =》 ‘2147483647’,
MIN_VERSIONS =》 ‘0’, KEEP_DELETED_CELLS =》 ‘false’, BLOCKSIZE =》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》 ‘tr
ue’}, {NAME =》 ‘note’, DATA_BLOCK_ENCODING =》 ‘NONE’, BLOOMFILTER =》 ‘ROW’, REPLICATION_SCOPE =》 ‘0’, VERSIONS =》
‘10’, COMPRESSION =》 ‘NONE’, MIN_VERSIONS =》 ‘0’, TTL =》 ‘2147483647’, KEEP_DELETED_CELLS =》 ‘false’, BLOCKSIZE
=》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》 ‘true’}, {NAME =》 ‘sysinfo’, DATA_BLOCK_ENCODING =》 ‘NONE’, BLOOM
FILTER =》 ‘ROW’, REPLICATION_SCOPE =》 ‘0’, COMPRESSION =》 ‘NONE’, VERSIONS =》 ‘10’, TTL =》 ‘2147483647’, MIN_VERS
IONS =》 ‘0’, KEEP_DELETED_CELLS =》 ‘true’, BLOCKSIZE =》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》 ‘true’}
1 row(s) in 0.0450 seconds
修改表,刪除三個(gè)列族,新增一個(gè)列族,代碼如下:
Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
String tablename = “rd_ns:itable”;
if(admin.tableExists(tablename)) {
try {
admin.disableTable(tablename);
//get the TableDescriptor of target table
HTableDescriptor newtd = admin.getTableDescriptor(Bytes.toBytes(“rd_ns:itable”));
//remove 3 useless column families
newtd.removeFamily(Bytes.toBytes(“note”));
newtd.removeFamily(Bytes.toBytes(“newcf”));
newtd.removeFamily(Bytes.toBytes(“sysinfo”));
//create HColumnDescriptor for new column family
HColumnDescriptor newhcd = new HColumnDescriptor(“action_log”);
newhcd.setMaxVersions(10);
newhcd.setKeepDeletedCells(true);
//add the new column family(HColumnDescriptor) to HTableDescriptor
newtd.addFamily(newhcd);
//modify target table struture
admin.modifyTable(Bytes.toBytes(“rd_ns:itable”),newtd);
admin.enableTable(tablename);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
admin.close();
修改之后:
hbase(main):015:0》 describe ‘rd_ns:itable’
DESCRIPTION ENABLED
‘rd_ns:itable’, {NAME =》 ‘a(chǎn)ction_log’, DATA_BLOCK_ENCODING =》 ‘NONE’, BLOOMFILTER =》 ‘ROW’, REPLICATION_SCOPE =》 true
‘0’, COMPRESSION =》 ‘NONE’, VERSIONS =》 ‘10’, TTL =》 ‘2147483647’, MIN_VERSIONS =》 ‘0’, KEEP_DELETED_CELLS =》 ‘tr
ue’, BLOCKSIZE =》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》 ‘true’}, {NAME =》 ‘info’, DATA_BLOCK_ENCODING =》 ‘
NONE’, BLOOMFILTER =》 ‘ROW’, REPLICATION_SCOPE =》 ‘0’, VERSIONS =》 ‘10’, COMPRESSION =》 ‘NONE’, MIN_VERSIONS =》 ‘
0’, TTL =》 ‘2147483647’, KEEP_DELETED_CELLS =》 ‘false’, BLOCKSIZE =》 ‘65536’, IN_MEMORY =》 ‘false’, BLOCKCACHE =》
‘true’}
1 row(s) in 0.0400 seconds
邏輯很簡(jiǎn)單:
通過(guò)admin.getTableDescriptor(Bytes.toBytes(“rd_ns:itable”))取得目標(biāo)表的描述對(duì)象,應(yīng)該就是取得指向該對(duì)象的指針了;
修改目標(biāo)表描述對(duì)象;
通過(guò)admin.modifyTable(Bytes.toBytes(“rd_ns:itable”),newtd)將修改后的描述對(duì)象應(yīng)用到目標(biāo)表。
(2)修改現(xiàn)有列族的屬性(setMaxVersions)
Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
String tablename = “rd_ns:itable”;
if(admin.tableExists(tablename)) {
try {
admin.disableTable(tablename);
//get the TableDescriptor of target table
HTableDescriptor htd = admin.getTableDescriptor(Bytes.toBytes(“rd_ns:itable”));
HColumnDescriptor infocf = htd.getFamily(Bytes.toBytes(“info”));
infocf.setMaxVersions(100);
//modify target table struture
admin.modifyTable(Bytes.toBytes(“rd_ns:itable”),htd);
admin.enableTable(tablename);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
admin.close();
5. 新增、更新數(shù)據(jù)Put
5.1.常用構(gòu)造函數(shù):
(1)指定行鍵
public Put(byte[] row)
參數(shù):row 行鍵
(2)指定行鍵和時(shí)間戳
public Put(byte[] row, long ts)
參數(shù):row 行鍵,ts 時(shí)間戳
(3)從目標(biāo)字符串中提取子串,作為行鍵
Put(byte[] rowArray, int rowOffset, int rowLength)
(4)從目標(biāo)字符串中提取子串,作為行鍵,并加上時(shí)間戳
Put(byte[] rowArray, int rowOffset, int rowLength, long ts)
5.2.常用方法:
(1)指定列族、限定符,添加值
add(byte[] family, byte[] qualifier, byte[] value)
(2)指定列族、限定符、時(shí)間戳,添加值
add(byte[] family, byte[] qualifier, long ts, byte[] value)
(3)設(shè)置寫(xiě)WAL(Write-Ahead-Log)的級(jí)別
public void setDurability(Durability d)
參數(shù)是一個(gè)枚舉值,可以有以下幾種選擇:
ASYNC_WAL : 當(dāng)數(shù)據(jù)變動(dòng)時(shí),異步寫(xiě)WAL日志
SYNC_WAL : 當(dāng)數(shù)據(jù)變動(dòng)時(shí),同步寫(xiě)WAL日志
FSYNC_WAL : 當(dāng)數(shù)據(jù)變動(dòng)時(shí),同步寫(xiě)WAL日志,并且,強(qiáng)制將數(shù)據(jù)寫(xiě)入磁盤(pán)
SKIP_WAL : 不寫(xiě)WAL日志
USE_DEFAULT : 使用HBase全局默認(rèn)的WAL寫(xiě)入級(jí)別,即SYNC_WAL
5.3.實(shí)例代碼
(1)插入行
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Put put = new Put(Bytes.toBytes(“100001”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“name”), Bytes.toBytes(“l(fā)ion”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“address”), Bytes.toBytes(“shangdi”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“age”), Bytes.toBytes(“30”));
put.setDurability(Durability.SYNC_WAL);
table.put(put);
table.close();
(2)更新行
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Put put = new Put(Bytes.toBytes(“100001”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“name”), Bytes.toBytes(“l(fā)ee”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“address”), Bytes.toBytes(“l(fā)ongze”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“age”), Bytes.toBytes(“31”));
put.setDurability(Durability.SYNC_WAL);
table.put(put);
table.close();
注意:
Put的構(gòu)造函數(shù)都需要指定行鍵,如果是全新的行鍵,則新增一行;如果是已有的行鍵,則更新現(xiàn)有行。
創(chuàng)建Put對(duì)象及put.add過(guò)程都是在構(gòu)建一行的數(shù)據(jù),創(chuàng)建Put對(duì)象時(shí)相當(dāng)于創(chuàng)建了行對(duì)象,add的過(guò)程就是往目標(biāo)行里添加cell,直到table.put才將數(shù)據(jù)插入表格;
以上代碼創(chuàng)建Put對(duì)象用的是構(gòu)造函數(shù)1,也可用構(gòu)造函數(shù)2,第二個(gè)參數(shù)是時(shí)間戳;
Put還有別的構(gòu)造函數(shù),請(qǐng)查閱官網(wǎng)API。
(3)從目標(biāo)字符串中提取子串,作為行鍵,構(gòu)建Put
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Put put = new Put(Bytes.toBytes(“100001_100002”),7,6);
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“name”), Bytes.toBytes(“show”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“address”), Bytes.toBytes(“caofang”));
put.add(Bytes.toBytes(“info”), Bytes.toBytes(“age”), Bytes.toBytes(“30”));
table.put(put);
table.close();
注意,關(guān)于:Put put = new Put(Bytes.toBytes(“100001_100002”),7,6)
第二個(gè)參數(shù)是偏移量,也就是行鍵從第一個(gè)參數(shù)的第幾個(gè)字符開(kāi)始截取;
第三個(gè)參數(shù)是截取長(zhǎng)度;
這個(gè)代碼實(shí)際是從 100001_100002 中截取了100002子串作為目標(biāo)行的行鍵。
6.刪除數(shù)據(jù)Delete
Delete類(lèi)用于刪除表中的一行數(shù)據(jù),通過(guò)HTable.delete來(lái)執(zhí)行該動(dòng)作。
在執(zhí)行Delete操作時(shí),HBase并不會(huì)立即刪除數(shù)據(jù),而是對(duì)需要?jiǎng)h除的數(shù)據(jù)打上一個(gè)“墓碑”標(biāo)記,直到當(dāng)Storefile合并時(shí),再清除這些被標(biāo)記上“墓碑”的數(shù)據(jù)。
如果希望刪除整行,用行鍵來(lái)初始化一個(gè)Delete對(duì)象即可。如果希望進(jìn)一步定義刪除的具體內(nèi)容,可以使用以下這些Delete對(duì)象的方法:
為了刪除指定的列族,可以使用deleteFamily
為了刪除指定列的多個(gè)版本,可以使用deleteColumns
為了刪除指定列的指定版本,可以使用deleteColumn,這樣的話(huà)就只會(huì)刪除版本號(hào)(時(shí)間戳)與指定版本相同的列。如果不指定時(shí)間戳,默認(rèn)只刪除最新的版本
下面詳細(xì)說(shuō)明構(gòu)造函數(shù)和常用方法:
6.1.構(gòu)造函數(shù)
(1)指定要?jiǎng)h除的行鍵
Delete(byte[] row)
刪除行鍵指定行的數(shù)據(jù)。
如果沒(méi)有進(jìn)一步的操作,使用該構(gòu)造函數(shù)將刪除行鍵指定的行中所有列族中所有列的所有版本!
(2)指定要?jiǎng)h除的行鍵和時(shí)間戳
Delete(byte[] row, long timestamp)
刪除行鍵和時(shí)間戳共同確定行的數(shù)據(jù)。
如果沒(méi)有進(jìn)一步的操作,使用該構(gòu)造函數(shù)將刪除行鍵指定的行中,所有列族中所有列的時(shí)間戳小于等于指定時(shí)間戳的數(shù)據(jù)版本。
注意:該時(shí)間戳僅僅和刪除行有關(guān),如果需要進(jìn)一步指定列族或者列,你必須分別為它們指定時(shí)間戳。
(3)給定一個(gè)字符串,目標(biāo)行鍵的偏移,截取的長(zhǎng)度
Delete(byte[] rowArray, int rowOffset, int rowLength)
(4)給定一個(gè)字符串,目標(biāo)行鍵的偏移,截取的長(zhǎng)度,時(shí)間戳
Delete(byte[] rowArray, int rowOffset, int rowLength, long ts)
6.2.常用方法
Delete deleteColumn(byte[] family, byte[] qualifier) 刪除指定列的最新版本的數(shù)據(jù)。
Delete deleteColumns(byte[] family, byte[] qualifier) 刪除指定列的所有版本的數(shù)據(jù)。
Delete deleteColumn(byte[] family, byte[] qualifier, long timestamp) 刪除指定列的指定版本的數(shù)據(jù)。
Delete deleteColumns(byte[] family, byte[] qualifier, long timestamp) 刪除指定列的,時(shí)間戳小于等于給定時(shí)間戳的所有版本的數(shù)據(jù)。
Delete deleteFamily(byte[] family) 刪除指定列族的所有列的所有版本數(shù)據(jù)。
Delete deleteFamily(byte[] family, long timestamp) 刪除指定列族的所有列中時(shí)間戳小于等于指定時(shí)間戳的所有數(shù)據(jù)。
Delete deleteFamilyVersion(byte[] family, long timestamp) 刪除指定列族中所有列的時(shí)間戳等于指定時(shí)間戳的版本數(shù)據(jù)。
voidsetTimestamp(long timestamp) 為Delete對(duì)象設(shè)置時(shí)間戳。
6.3.實(shí)例代碼
(1)刪除整行的所有列族、所有行、所有版本
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Delete delete = new Delete(Bytes.toBytes(“000”));
table.delete(delete);
table.close();
(2)刪除指定列的最新版本
以下是刪除之前的數(shù)據(jù),注意看100003行的info:address,這是該列最新版本的數(shù)據(jù),值是caofang1,在這之前的版本值是caofang:
hbase(main):007:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405390959464, value=caofang1
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0270 seconds
執(zhí)行以下代碼:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Delete delete = new Delete(Bytes.toBytes(“100003”));
delete.deleteColumn(Bytes.toBytes(“info”), Bytes.toBytes(“address”));
table.delete(delete);
table.close();
然后查看數(shù)據(jù),發(fā)現(xiàn)100003列的info:address列的值顯示為前一個(gè)版本的caofang了!其余值均不變:
hbase(main):008:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405390728175, value=caofang
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0560 seconds
(3)刪除指定列的所有版本
接以上場(chǎng)景,執(zhí)行以下代碼:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Delete delete = new Delete(Bytes.toBytes(“100003”));
delete.deleteColumns(Bytes.toBytes(“info”), Bytes.toBytes(“address”));
table.delete(delete);
table.close();
然后我們會(huì)發(fā)現(xiàn),100003行的整個(gè)info:address列都沒(méi)了:
hbase(main):009:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0240 seconds
(4)刪除指定列族中所有列的時(shí)間戳等于指定時(shí)間戳的版本數(shù)據(jù)
為了演示效果,我已經(jīng)向100003行的info:address列新插入一條數(shù)據(jù)
hbase(main):010:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405391883886, value=shangdi
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0250 seconds
現(xiàn)在,我們的目的是刪除info列族中,時(shí)間戳為1405390959464的所有列數(shù)據(jù):
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Delete delete = new Delete(Bytes.toBytes(“100003”));
delete.deleteFamilyVersion(Bytes.toBytes(“info”), 1405390959464L);
table.delete(delete);
table.close();
hbase(main):011:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405391883886, value=shangdi
100003 column=info:age, timestamp=1405390728175, value=30
100003 column=info:name, timestamp=1405390728175, value=show
3 row(s) in 0.0250 seconds
可以看到,100003行的info列族,已經(jīng)不存在時(shí)間戳為1405390959464的數(shù)據(jù),比它更早版本的數(shù)據(jù)被查詢(xún)出來(lái),而info列族中時(shí)間戳不等于1405390959464的address列,不受該delete的影響。
7.獲取單行Get
如果希望獲取整行數(shù)據(jù),用行鍵初始化一個(gè)Get對(duì)象就可以,如果希望進(jìn)一步縮小獲取的數(shù)據(jù)范圍,可以使用Get對(duì)象的以下方法:
如果希望取得指定列族的所有列數(shù)據(jù),使用addFamily添加所有的目標(biāo)列族即可;
如果希望取得指定列的數(shù)據(jù),使用addColumn添加所有的目標(biāo)列即可;
如果希望取得目標(biāo)列的指定時(shí)間戳范圍的數(shù)據(jù)版本,使用setTimeRange;
如果僅希望獲取目標(biāo)列的指定時(shí)間戳版本,則使用setTimestamp;
如果希望限制每個(gè)列返回的版本數(shù),使用setMaxVersions;
如果希望添加過(guò)濾器,使用setFilter
下面詳細(xì)描述構(gòu)造函數(shù)及常用方法:
7.1.構(gòu)造函數(shù)
Get的構(gòu)造函數(shù)很簡(jiǎn)單,只有一個(gè)構(gòu)造函數(shù):Get(byte[] row) 參數(shù)是行鍵。
7.2.常用方法
Get addFamily (byte[] family) 指定希望獲取的列族
Get addColumn (byte[] family, byte[] qualifier) 指定希望獲取的列
Get setTimeRange (long minStamp, long maxStamp) 設(shè)置獲取數(shù)據(jù)的時(shí)間戳范圍
Get setTimeStamp (long timestamp) 設(shè)置獲取數(shù)據(jù)的時(shí)間戳
Get setMaxVersions (int maxVersions) 設(shè)定獲取數(shù)據(jù)的版本數(shù)
Get setMaxVersions() 設(shè)定獲取數(shù)據(jù)的所有版本
Get setFilter (Filter filter) 為Get對(duì)象添加過(guò)濾器,過(guò)濾器詳解請(qǐng)參見(jiàn):http://blog.csdn.net/u010967382/article/details/37653177
void setCacheBlocks (boolean cacheBlocks) 設(shè)置該Get獲取的數(shù)據(jù)是否緩存在內(nèi)存中
7.3.實(shí)測(cè)代碼
測(cè)試表的所有數(shù)據(jù):
hbase(main):016:0》 scan ‘rd_ns:leetable’
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405407883218, value=qinghe
100003 column=info:age, timestamp=1405407883218, value=28
100003 column=info:name, timestamp=1405407883218, value=shichao
3 row(s) in 0.0250 seconds
(1)獲取行鍵指定行的所有列族、所有列的最新版本數(shù)據(jù)
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Get get = new Get(Bytes.toBytes(“100003”));
Result r = table.get(get);
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))
);
}
table.close();
代碼輸出:
Rowkey : 100003 Familiy:Quilifier : address Value : qinghe
Rowkey : 100003 Familiy:Quilifier : age Value : 28
Rowkey : 100003 Familiy:Quilifier : name Value : shichao
(2)獲取行鍵指定行中,指定列的最新版本數(shù)據(jù)
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Get get = new Get(Bytes.toBytes(“100003”));
get.addColumn(Bytes.toBytes(“info”), Bytes.toBytes(“name”));
Result r = table.get(get);
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))
);
}
table.close();
代碼輸出:
Rowkey : 100003 Familiy:Quilifier : name Value : shichao
(3)獲取行鍵指定的行中,指定時(shí)間戳的數(shù)據(jù)
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:leetable”);
Get get = new Get(Bytes.toBytes(“100003”));
get.setTimeStamp(1405407854374L);
Result r = table.get(get);
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))
);
}
table.close();
代碼輸出了上面scan命令輸出中沒(méi)有展示的歷史數(shù)據(jù):
Rowkey : 100003 Familiy:Quilifier : address Value : huangzhuang
Rowkey : 100003 Familiy:Quilifier : age Value : 32
Rowkey : 100003 Familiy:Quilifier : name Value : lily
(4)獲取行鍵指定的行中,所有版本的數(shù)據(jù)
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:itable”);
Get get = new Get(Bytes.toBytes(“100003”));
get.setMaxVersions();
Result r = table.get(get);
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();
代碼輸出:
Rowkey : 100003 Familiy:Quilifier : address Value : xierqi Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : address Value : shangdi Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : address Value : longze Time : 1405417448414
Rowkey : 100003 Familiy:Quilifier : age Value : 29 Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : age Value : 30 Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : age Value : 31 Time : 1405417448414
Rowkey : 100003 Familiy:Quilifier : name Value : leon Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : name Value : lee Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : name Value : lion Time : 1405417448414
?
8.獲取多行Scan
Scan對(duì)象可以返回滿(mǎn)足給定條件的多行數(shù)據(jù)。如果希望獲取所有的行,直接初始化一個(gè)Scan對(duì)象即可。如果希望限制掃描的行范圍,可以使用以下方法:
如果希望獲取指定列族的所有列,可使用addFamily方法來(lái)添加所有希望獲取的列族
如果希望獲取指定列,使用addColumn方法來(lái)添加所有列
通過(guò)setTimeRange方法設(shè)定獲取列的時(shí)間范圍
通過(guò)setTimestamp方法指定具體的時(shí)間戳,只返回該時(shí)間戳的數(shù)據(jù)
通過(guò)setMaxVersions方法設(shè)定最大返回的版本數(shù)
通過(guò)setBatch方法設(shè)定返回?cái)?shù)據(jù)的最大行數(shù)
通過(guò)setFilter方法為Scan對(duì)象添加過(guò)濾器,過(guò)濾器詳解請(qǐng)參見(jiàn):http://blog.csdn.net/u010967382/article/details/37653177
Scan的結(jié)果數(shù)據(jù)是可以緩存在內(nèi)存中的,可以通過(guò)getCaching()方法來(lái)查看當(dāng)前設(shè)定的緩存條數(shù),也可以通過(guò)setCaching(int caching)來(lái)設(shè)定緩存在內(nèi)存中的行數(shù),緩存得越多,以后查詢(xún)結(jié)果越快,同時(shí)也消耗更多內(nèi)存。此外,通過(guò)setCacheBlocks方法設(shè)置是否緩存Scan的結(jié)果數(shù)據(jù)塊,默認(rèn)為true
我們可以通過(guò)setMaxResultSize(long)方法來(lái)設(shè)定Scan返回的結(jié)果行數(shù)。
下面是官網(wǎng)文檔中的一個(gè)入門(mén)示例:假設(shè)表有幾行鍵值為 “row1”, “row2”, “row3”,還有一些行有鍵值 “abc1”, “abc2”, 和 “abc3”,目標(biāo)是返回“row”打頭的行:
HTable htable = 。.. // instantiate HTable
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes(“cf”),Bytes.toBytes(“attr”));
scan.setStartRow( Bytes.toBytes(“row”)); // start key is inclusive
scan.setStopRow( Bytes.toBytes(“row” + (char)0)); // stop key is exclusive
ResultScanner rs = htable.getScanner(scan);
try {
for (Result r = rs.next(); r != null; r = rs.next()) {
// process result.。.
} finally {
rs.close(); // always close the ResultScanner!
}
8.1.常用構(gòu)造函數(shù)
(1)創(chuàng)建掃描所有行的Scan
Scan()
(2)創(chuàng)建Scan,從指定行開(kāi)始掃描,
Scan(byte[] startRow)
參數(shù):startRow行鍵
注意:如果指定行不存在,從下一個(gè)最近的行開(kāi)始
(3)創(chuàng)建Scan,指定起止行
Scan(byte[] startRow, byte[] stopRow)
參數(shù):startRow起始行,stopRow終止行
注意:startRow 《= 結(jié)果集 《 stopRow
(4)創(chuàng)建Scan,指定起始行和過(guò)濾器
Scan(byte[] startRow, Filter filter)
參數(shù):startRow起始行,filter過(guò)濾器
注意:過(guò)濾器的功能和構(gòu)造參見(jiàn)http://blog.csdn.net/u010967382/article/details/37653177
8.2.常用方法
Scan setStartRow(byte[] startRow) 設(shè)置Scan的開(kāi)始行,默認(rèn)結(jié)果集包含該行。如果希望結(jié)果集不包含該行,可以在行鍵末尾加上0。
Scan setStopRow(byte[] stopRow) 設(shè)置Scan的結(jié)束行,默認(rèn)結(jié)果集不包含該行。如果希望結(jié)果集包含該行,可以在行鍵末尾加上0。
Scan setTimeRange(long minStamp, long maxStamp) 掃描指定時(shí)間范圍的數(shù)據(jù)
Scan setTimeStamp(long timestamp) 掃描指定時(shí)間的數(shù)據(jù)
Scan addColumn(byte[] family, byte[] qualifier) 指定掃描的列
Scan addFamily(byte[] family) 指定掃描的列族
Scan setFilter(Filter filter) 為Scan設(shè)置過(guò)濾器
Scan setReversed(boolean reversed) 設(shè)置Scan的掃描順序,默認(rèn)是正向掃描(false),可以設(shè)置為逆向掃描(true)。注意:該方法0.98版本以后才可用??!
Scan setMaxVersions() 獲取所有版本的數(shù)據(jù)
Scan setMaxVersions(int maxVersions) 設(shè)置獲取的最大版本數(shù)
void setCaching(int caching) 設(shè)定緩存在內(nèi)存中的行數(shù),緩存得越多,以后查詢(xún)結(jié)果越快,同時(shí)也消耗更多內(nèi)存
void setRaw(boolean raw) 激活或者禁用raw模式。如果raw模式被激活,Scan將返回所有已經(jīng)被打上刪除標(biāo)記但尚未被真正刪除的數(shù)據(jù)。該功能僅用于激活了KEEP_DELETED_ROWS的列族,即列族開(kāi)啟了hcd.setKeepDeletedCells(true)。Scan激活raw模式后,就不能指定任意的列,否則會(huì)報(bào)錯(cuò)
Enable/disable “raw” mode for this scan. If “raw” is enabled the scan will return all delete marker and deleted rows that have not been collected, yet. This is mostly useful for Scan on column families that have KEEP_DELETED_ROWS enabled. It is an error to specify any column when “raw” is set.
hcd.setKeepDeletedCells(true);
8.3.實(shí)測(cè)代碼
(1)掃描表中的所有行的最新版本數(shù)據(jù)
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:itable”);
Scan s = new Scan();
ResultScanner rs = table.getScanner(s);
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();
代碼輸出:
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 : 100002 Familiy:Quilifier : address Value : shangdi Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : age Value : 28 Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : name Value : shichao Time : 1405417426693
Rowkey : 100003 Familiy:Quilifier : address Value : xierqi Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : age Value : 29 Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : name Value : leon Time : 1405417500485
(2)掃描指定行鍵范圍,通過(guò)末尾加0,使得結(jié)果集包含StopRow
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:itable”);
Scan s = new Scan();
s.setStartRow(Bytes.toBytes(“100001”));
s.setStopRow(Bytes.toBytes(“1000020”));
ResultScanner rs = table.getScanner(s);
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();
代碼輸出:
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 : 100002 Familiy:Quilifier : address Value : shangdi Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : age Value : 28 Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : name Value : shichao Time : 1405417426693
(3)返回所有已經(jīng)被打上刪除標(biāo)記但尚未被真正刪除的數(shù)據(jù)
本測(cè)試針對(duì)rd_ns:itable表的100003行。
如果使用get結(jié)合setMaxVersions()方法能返回所有未刪除的數(shù)據(jù),輸出如下:
Rowkey : 100003 Familiy:Quilifier : address Value : huilongguan Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : address Value : shangdi Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : age Value : new29 Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : name Value : liyang Time : 1405494141522
然而,使用Scan強(qiáng)大的s.setRaw(true)方法,可以獲得所有已經(jīng)被打上刪除標(biāo)記但尚未被真正刪除的數(shù)據(jù)。
代碼如下:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:itable”);
Scan s = new Scan();
s.setStartRow(Bytes.toBytes(“100003”));
s.setRaw(true);
s.setMaxVersions();
ResultScanner rs = table.getScanner(s);
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();
輸出結(jié)果如下:
Rowkey : 100003 Familiy:Quilifier : address Value : huilongguan Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : address Value : Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : address Value : xierqi Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : address Value : shangdi Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : address Value : Time : 1405417448414
Rowkey : 100003 Familiy:Quilifier : address Value : longze Time : 1405417448414
Rowkey : 100003 Familiy:Quilifier : age Value : new29 Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : age Value : Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : age Value : Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : age Value : 29 Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : age Value : 30 Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : age Value : 31 Time : 1405417448414
Rowkey : 100003 Familiy:Quilifier : name Value : liyang Time : 1405494141522
Rowkey : 100003 Familiy:Quilifier : name Value : Time : 1405493879419
Rowkey : 100003 Familiy:Quilifier : name Value : leon Time : 1405417500485
Rowkey : 100003 Familiy:Quilifier : name Value : lee Time : 1405417477465
Rowkey : 100003 Familiy:Quilifier : name Value : lion Time : 1405417448414
(4)結(jié)合過(guò)濾器,獲取所有age在25到30之間的行
目前的數(shù)據(jù):
hbase(main):049: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.0240 seconds
代碼:
Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, “rd_ns:itable”);
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
Bytes.toBytes(“info”),
Bytes.toBytes(“age”),
CompareOp.GREATER_OR_EQUAL,
Bytes.toBytes(“25”)
);
SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
Bytes.toBytes(“info”),
Bytes.toBytes(“age”),
CompareOp.LESS_OR_EQUAL,
Bytes.toBytes(“30”)
);
filterList.addFilter(filter1);
filterList.addFilter(filter2);
Scan scan = new Scan();
scan.setFilter(filterList);
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();
代碼輸出:
Rowkey : 100002 Familiy:Quilifier : address Value : shangdi Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : age Value : 28 Time : 1405417426693
Rowkey : 100002 Familiy:Quilifier : name Value : shichao Time : 1405417426693
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
注意:
HBase對(duì)列族、列名大小寫(xiě)敏感
評(píng)論
查看更多