一、 實驗目的
本次實驗通過使用終端和Java API對hbase進行增刪改查操作,學習非關系型數據庫的結構以及如何操作,理解非關系型數據庫與關系數據庫的對比,掌握如何使用菲關系型數據庫hbase。
二、 實驗內容
盡可能完成老師給出的內容,做了多少就寫多少
三、 實驗思路、結構
先在Linux命令行的方式下實現在hbase中建表,增刪改查操作
然后再使用Elipse利用Java編程實現在hbase中建表,增刪改查操作。
四、 實驗結果
HBase中用create命令創建表,具體如下:
此時,即創建了一個“student”表,屬性有:Sname,Ssex,Sage,Sdept,course。因為HBase的表中會有一個系統默認的屬性作為行鍵,無需自行創建,默認為put命令操作中表名后第一個數據。創建完“student”表后,可通過describe命令查看“student”表的基本信息。命令執行截圖如下:
然后執行HBase的增刪改查操作。在添加數據時,HBase會自動為添加的數據添加一個時間戳,故在需要修改數據時,只需直接添加數據,HBase即會生成一個新的版本,從而完成“改”操作,舊的版本依舊保留,系統會定時回收垃圾數據,只留下最新的幾個版本,保存的版本數可以在創建表的時候指定。
1.添加數據
HBase中用put命令添加數據,注意:一次只能為一個表的一行數據的一個列,也就是一個單元格添加一個數據,所以直接用shell命令插入數據效率很低,在實際應用中,一般都是利用編程操作數據。
此時為student表添加了學號為95001,名字為LiYing的一行數據,其行鍵為95001。因為HBase的表中會有一個系統默認的屬性作為行鍵,無需自行創建,默認為put命令操作中表名后第一個數據。
此時即為95001行下的course列族的math列添加了一個數據。
2.刪除數據
在HBase中用delete以及deleteall命令進行刪除數據操作,它們的區別是:1. delete用於刪除一個數據,是put的反向操作;2. deleteall操作用於刪除一行數據。
此時刪除了student表中95001行下的Ssex列的所有數據。
deleteall命令
Deleteall ‘student’, ‘95001’命令刪除了95001行的所有列,即該行的全部數據。
3.查看數據
HBase中有兩個用於查看數據的命令:1. get命令,用於查看表的某一行數據;2. scan命令用於查看某個表的全部數據。
get命令
返回的是‘student’表‘95001’行的數據。
scan命令
此時返回的是’student’表的全部數據。
還可以查詢標的歷史數據
查詢表的歷史版本,需要兩步。
(1).在創建表的時候,指定保存的版本數(假設指定為5)
(2).插入數據然后更新數據,使其產生歷史版本數據,注意:這里插入數據和更新數據都是用put命令
(3).查詢時,指定查詢的歷史版本數。默認會查詢出最新的數據。(有效取值為1到5)
4.刪除表
刪除表有兩步,第一步先讓該表不可用,第二步刪除表。
使用Elipse編程實現對hbase的增刪改查
代碼為:
1 import org.apache.hadoop.conf.Configuration; 2 import org.apache.hadoop.hbase.*; 3 import org.apache.hadoop.hbase.client.*; 4 import java.io.IOException; 5 6 public class ExampleForHbase 7 { 8 public static Configuration configuration; 9 public static Connection connection; 10 public static Admin admin; 11 12 //主函數中的語句請逐句執行,只需刪除其前的//即可,如:執行insertRow時請將其他語句注釋 13 public static void main(String[] args)throws IOException 14 { 15 //創建一個表,表名為Score,列族為sname,course 16 //createTable("Score",new String[]{"sname","course"}); 17 18 //在Score表中插入一條數據,其行鍵為95001,sname為Mary(因為sname列族下沒有子列所以第四個參數為空) 19 //等價命令:put 'Score','95001','sname','Mary' 20 //insertRow("Score", "95001", "sname", "", "Mary"); 21 //在Score表中插入一條數據,其行鍵為95001,course:Math為88(course為列族,Math為course下的子列) 22 //等價命令:put 'Score','95001','score:Math','88' 23 //insertRow("Score", "95001", "course", "Math", "88"); 24 //在Score表中插入一條數據,其行鍵為95001,course:English為85(course為列族,English為course下的子列) 25 //等價命令:put 'Score','95001','score:English','85' 26 //insertRow("Score", "95001", "course", "English", "85"); 27 28 //1、刪除Score表中指定列數據,其行鍵為95001,列族為course,列為Math 29 //執行這句代碼前請deleteRow方法的定義中,將刪除指定列數據的代碼取消注釋注釋,將刪除制定列族的代碼注釋 30 //等價命令:delete 'Score','95001','score:Math' 31 //deleteRow("Score", "95001", "course", "Math"); 32 33 //2、刪除Score表中指定列族數據,其行鍵為95001,列族為course(95001的Math和English的值都會被刪除) 34 //執行這句代碼前請deleteRow方法的定義中,將刪除指定列數據的代碼注釋,將刪除制定列族的代碼取消注釋 35 //等價命令:delete 'Score','95001','score' 36 //deleteRow("Score", "95001", "course", ""); 37 38 //3、刪除Score表中指定行數據,其行鍵為95001 39 //執行這句代碼前請deleteRow方法的定義中,將刪除指定列數據的代碼注釋,以及將刪除制定列族的代碼注釋 40 //等價命令:deleteall 'Score','95001' 41 //deleteRow("Score", "95001", "", ""); 42 43 //查詢Score表中,行鍵為95001,列族為course,列為Math的值 44 //getData("Score", "95001", "course", "Math"); 45 //查詢Score表中,行鍵為95001,列族為sname的值(因為sname列族下沒有子列所以第四個參數為空) 46 //getData("Score", "95001", "sname", ""); 47 48 //刪除Score表 49 //deleteTable("Score"); 50 } 51 52 //建立連接 53 public static void init() 54 { 55 configuration = HBaseConfiguration.create(); 56 configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase"); 57 try 58 { 59 connection = ConnectionFactory.createConnection(configuration); 60 admin = connection.getAdmin(); 61 } 62 catch (IOException e) 63 { 64 e.printStackTrace(); 65 } 66 } 67 //關閉連接 68 public static void close() 69 { 70 try 71 { 72 if(admin != null) 73 { 74 admin.close(); 75 } 76 if(null != connection) 77 { 78 connection.close(); 79 } 80 } 81 catch (IOException e) 82 { 83 e.printStackTrace(); 84 } 85 } 86 87 /** 88 * 建表。HBase的表中會有一個系統默認的屬性作為主鍵,主鍵無需自行創建,默認為put命令操作中表名后第一個數據,因此此處無需創建id列 89 * @param myTableName 表名 90 * @param colFamily 列族名 91 * @throws IOException 92 */ 93 public static void createTable(String myTableName,String[] colFamily) throws IOException 94 { 95 96 init(); 97 TableName tableName = TableName.valueOf(myTableName); 98 99 if(admin.tableExists(tableName)) 100 { 101 System.out.println("talbe is exists!"); 102 } 103 else 104 { 105 HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName); 106 for(String str:colFamily) 107 { 108 HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str); 109 hTableDescriptor.addFamily(hColumnDescriptor); 110 } 111 admin.createTable(hTableDescriptor); 112 System.out.println("create table success"); 113 } 114 close(); 115 } 116 /** 117 * 刪除指定表 118 * @param tableName 表名 119 * @throws IOException 120 */ 121 public static void deleteTable(String tableName) throws IOException 122 { 123 init(); 124 TableName tn = TableName.valueOf(tableName); 125 if (admin.tableExists(tn)) 126 { 127 admin.disableTable(tn); 128 admin.deleteTable(tn); 129 } 130 close(); 131 } 132 133 /** 134 * 查看已有表 135 * @throws IOException 136 */ 137 public static void listTables() throws IOException 138 { 139 init(); 140 HTableDescriptor hTableDescriptors[] = admin.listTables(); 141 for(HTableDescriptor hTableDescriptor :hTableDescriptors) 142 { 143 System.out.println(hTableDescriptor.getNameAsString()); 144 } 145 close(); 146 } 147 /** 148 * 向某一行的某一列插入數據 149 * @param tableName 表名 150 * @param rowKey 行鍵 151 * @param colFamily 列族名 152 * @param col 列名(如果其列族下沒有子列,此參數可為空) 153 * @param val 值 154 * @throws IOException 155 */ 156 public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException 157 { 158 init(); 159 Table table = connection.getTable(TableName.valueOf(tableName)); 160 Put put = new Put(rowKey.getBytes()); 161 put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes()); 162 table.put(put); 163 table.close(); 164 close(); 165 } 166 167 /** 168 * 刪除數據 169 * @param tableName 表名 170 * @param rowKey 行鍵 171 * @param colFamily 列族名 172 * @param col 列名 173 * @throws IOException 174 */ 175 public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException 176 { 177 init(); 178 Table table = connection.getTable(TableName.valueOf(tableName)); 179 Delete delete = new Delete(rowKey.getBytes()); 180 //刪除指定列族的所有數據 181 //delete.addFamily(colFamily.getBytes()); 182 //刪除指定列的數據 183 //delete.addColumn(colFamily.getBytes(), col.getBytes()); 184 185 table.delete(delete); 186 table.close(); 187 close(); 188 } 189 /** 190 * 根據行鍵rowkey查找數據 191 * @param tableName 表名 192 * @param rowKey 行鍵 193 * @param colFamily 列族名 194 * @param col 列名 195 * @throws IOException 196 */ 197 public static void getData(String tableName,String rowKey,String colFamily,String col)throws IOException 198 { 199 init(); 200 Table table = connection.getTable(TableName.valueOf(tableName)); 201 Get get = new Get(rowKey.getBytes()); 202 get.addColumn(colFamily.getBytes(),col.getBytes()); 203 Result result = table.get(get); 204 showCell(result); 205 table.close(); 206 close(); 207 } 208 /** 209 * 格式化輸出 210 * @param result 211 */ 212 public static void showCell(Result result) 213 { 214 Cell[] cells = result.rawCells(); 215 for(Cell cell:cells) 216 { 217 System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" "); 218 System.out.println("Timetamp:"+cell.getTimestamp()+" "); 219 System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" "); 220 System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" "); 221 System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" "); 222 } 223 } 224 }
建表成功
在執行完代碼中的所有插入操作以后可以看到表中數據為:
執行三個不同層次的刪除操作后表中已經沒有數據了
再重新執行一個插入數據的操作
然后執行第一個getData操作
再執行第二個getData操作
最后刪除表。
五、 心得體會
做實驗的時候要細心,注意具體導入的是哪個地方的jar包