wiki:waue/2009/0626
hbase 0.19 程式設計

前言

  • hbase 已經到0.19.3了,可惜的是 hbase 0.18.1的api及文件都已經從官方網頁被拿掉了,所幸hbase 0.18 與hbase 0.19相差無幾
  • hbase 0.1.3 到 hbase 0.19.3 中間好像已經包含了十幾代,但是其實類似java 1.4 直接跳躍 到 java 5 一樣,hbase 0.1.3 -> hbase 0.2.x -> hbase 0.18.x -> hbase 0.19.x
    • 從 hbase 0.18.x 之後,其版本名稱就直接對應hadoop 的版本名稱,如 hbase 0.18 搭配 hadoop 0.18 , hbase 0.19 搭配hadoop 0.19
  • 筆者開發hbase時是 hbase 0.13的時代,現在又重拾舊業,發現已經差很多了。如撈取資料的方式:
    • hbase 0.13 : select * from 'table_name'
    • hbase 0.19 : scan 'table_name'

資料庫結構

table A

column_family:column_quolify1 column_family:column_quolify2 column_family:column_quolify3
row : time stamp 2 cell_value1 cell_value2 cell_value3
row : time stamp 1 cell_value1 cell_value2 cell_value3
  • 因此 table A這個資料表,總共有二度的空間,每一度空間又有二維結構。
    • 每個 column_family有許多column_quolify1
    • 每個 row 又分許多 timestamp

程式碼

  • 設計Hbase 的程式,首先要先規劃要建構怎樣功能的程式碼,在看需要用到什麼類別,類別產生出的物件的function可以靠eclipse產生(alt+/)再來挑選

宣告

  • 定義宣告以下參數
String table_name = "waue"; 
String colomn_family = "family:";
String column_quolify= "qf";
String hbase_row = "w-row";
String value = "yes ! good !";

必要條件 資料表屬性:HBaseConfiguration

  • 首先,建立HTableDescriptor 物件,用來設定資料表屬性,為必要條件。
HBaseConfiguration config = new HBaseConfiguration();

資料表的特權操作:HBaseAdmin

  • HBaseAdmin 用來執行資料庫的建立刪除操作,下面這段是用來檢查是否已經存在這個資料表,沒有的話則新增, 新增時需要用到HTableDescriptor這個類別來新增Column_Family這個成員。此非必要條件,因為不見得每次執行程式都要新建一個表單

  • 注意: 在此colomn_family 的後面要以:結尾,如" family:"
HBaseAdmin admin = new HBaseAdmin(config);

if (!admin.tableExists(table_name)) {
  System.out.println("HTable : " + table_name
      + "  creating ... please wait");
  HTableDescriptor tableDesc = new HTableDescriptor(table_name);
  // add column family
  tableDesc.addFamily(new HColumnDescriptor(colomn_family));
  admin.createTable(tableDesc);
}

新增/刪除 資料表內容:BatchUpdate

  • 接著,我們用!BatchUpdate來加入表單內容,我們首先用建構值填入hbase_row,接著用put放入值,用delete刪除值。
  • 此非必要條件(也就是沒有用到這個類別程式也能跑),但若是希望能新增或刪除資料的話還是得用到它

注意:這個類別不需要其他類別支援。

BatchUpdate batchUpdate = new BatchUpdate(hbase_row);
batchUpdate.put(colomn_family+column_quolify, Bytes.toBytes(value));
batchUpdate.delete(colomn_family+"cellIWantDeleted");

資料表內容:HTable

  • HTable 類別在此是用來把之前的建構的內容寫入 ,之後還會用這個類別取得資料表內容,因此也算是必要條件
  • HTable 類別用來連接HBaseConfiguration與BatchUpdate,如此完成表單建立 這個類別填入HBaseConfiguration與table_name的建構值,並用commit這個函式輸入之前!BatchUpdate建立的表單資料。
HTable table = new HTable(config, table_name);
table.commit(batchUpdate);
  • 如果你已經知道資料表中的 "row" "colomn_family" "column_quolify" 的資訊,可以用下列方法把該cell的值印出來。

注意: Hbase內的資料屬性雖然是byte,但要用 org.apache.hadoop.hbase.util.Bytes 的 toString(值) 才可以轉出正確格式

Cell cell = table.get(hbase_row, colomn_family+column_quolify);
// System.out.print(cell.getValue()); 會印出亂碼,因為資料格式不正確
System.out.print(Bytes.toString(cell.getValue()));  // cell value = yes ! good !

掃瞄資料表:Scanner

  • 接下來的程式碼用來印出資料表內容,因此需要用到HTable
  • Scanner連接到HBase後,怎麼把內容萃取出來呢? 用到 RowResult承接 Scanner.next()方法,然而一個row裡面,會有 許多colomn_family,每個colomn_family又會有自己的column_quolify,形成colomn_family:column_quolify的二維結構。
  • 提供兩個方法 [法一] [法二],方法都一樣,只是步驟有點不同
    • getRow() : 把row的名稱秀出來
    • get(colomn_family:column_quolify) : 把該cell的值秀出來
  • for (RowResult result : scanner) 可以看成是 for (int i=0; i< scanner.length; i++){ RowResult result[i] = scanner[i];
    • 但是 scanner沒有 hasnext 或 length的方法,因此用for還滿簡潔的

Scanner scanner = table.getScanner(new String[] { colomn_family+column_quolify });

// 法一
RowResult rowResult = scanner.next();
while (rowResult != null) {

  System.out.println("Found row: "
      + Bytes.toString(rowResult.getRow())
      + " with value: "
      + rowResult.get(Bytes
          .toBytes(colomn_family+column_quolify)));
  rowResult = scanner.next();
}// 法一完

//法二
for (RowResult result : scanner) {
  System.out.println("Found row: "
      + Bytes.toString(result.getRow())
      + " with value: "
      + result.get(Bytes
          .toBytes(colomn_family+column_quolify)));
}// 法二完

scanner.close();

完整程式碼如下

  • 完整程式碼如下
import java.io.IOException;

import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Scanner;
import org.apache.hadoop.hbase.io.BatchUpdate;
import org.apache.hadoop.hbase.io.Cell;
import org.apache.hadoop.hbase.io.RowResult;
import org.apache.hadoop.hbase.util.Bytes;

public class hbase {

	public static void main(String args[]) throws IOException {

		String table_name = "waue"; 
		String colomn_family = "family:";
		String column_quolify= "qf";
		String hbase_row = "w-row";
		String value = "0911311311";
		
		HBaseConfiguration config = new HBaseConfiguration();


		HBaseAdmin admin = new HBaseAdmin(config);
		if (!admin.tableExists(table_name)) {
			System.out.println("HTable : " + table_name
					+ "  creating ... please wait");
			HTableDescriptor tableDesc = new HTableDescriptor(table_name);
			// add column family
			tableDesc.addFamily(new HColumnDescriptor(colomn_family));
			admin.createTable(tableDesc);
		}

		HTable table = new HTable(config, table_name);


		BatchUpdate batchUpdate = new BatchUpdate(hbase_row);


		batchUpdate.put(colomn_family+column_quolify, Bytes
				.toBytes(value));


		batchUpdate.delete(colomn_family+"cellIWantDeleted");


		table.commit(batchUpdate);


		Cell cell = table.get(hbase_row, colomn_family+column_quolify);
		System.out.print(cell.getValue());


		Scanner scanner =
		table.getScanner(new String[] { colomn_family+column_quolify });

		RowResult rowResult = scanner.next();

		while (rowResult != null) {

			System.out.println("Found row: "
					+ Bytes.toString(rowResult.getRow())
					+ " with value: "
					+ rowResult.get(Bytes
							.toBytes(colomn_family+column_quolify)));
			rowResult = scanner.next();
		}

		for (RowResult result : scanner) {
			System.out.println("Found row: "
					+ Bytes.toString(result.getRow())
					+ " with value: "
					+ result.get(Bytes
							.toBytes(colomn_family+column_quolify)));
		}

		scanner.close();
	}
}


Last modified 11 years ago Last modified on Jul 24, 2009, 11:32:01 AM