//石家庄铁道大学,软件工程系:沧月88
实验环境:
1、 操作系统:Linux(建议Ubuntu16.04);
2、 Hadoop版本:2.7.1;
3、 JDK版本:1.7或以上版本; 4、 Java IDE:Eclipse。
实验目的:
1、 理解HBase在Hadoop体系结构中的角色;
2、 熟练使用HBase操作常用的Shell命令;
3、 熟悉HBase操作常用的Java API。
实验步骤:
(一)编程实现以下指定功能,并用 Hadoop 提供的 HBase Shell 命令完成相同任务:
(1) 列出 HBase 所有的表的相关信息,例如表名;
list
(2) 在终端打印出指定的表的所有记录数据;
scan '表名'
(3) 向已经创建好的表添加和删除指定的列族或列;
alter '表名',NAME=>'列名'
alter '表名',NAME=>'列名',METHOD=>'delete'
(4) 清空指定的表的所有记录数据;
truncate '表名'
(5) 统计表的行数。
count '表名'
(二)HBase 数据库操作
1. 现有以下关系型数据库中的表和数据,要求将其转换为适合于 HBase 存储的表并插入数 据:
学生表(Student)
学号(S_No) |
姓名(S_Name) |
性别(S_Sex) |
年龄(S_Age) |
2015001 |
Zhangsan |
male |
23 |
2015003 |
Mary |
female |
22 |
2015003 |
Lisi |
male |
24 |
课程表(Course)
课程号(C_No) |
课程名(C_Name) |
学分(C_Credit) |
123001 |
Math |
2.0 |
123002 |
Computer Science |
5.0 |
123003 |
English |
3.0 |
选课表(SC)
学号(SC_Sno) |
课程号(SC_Cno) |
成绩(SC_Score) |
2015001 |
123001 |
86 |
2015001 |
123003 |
69 |
2015002 |
123002 |
77 |
2015002 |
123003 |
99 |
2015003 |
123001 |
98 |
2015003 |
123002 |
95 |
创建表格思路:
(1)关系型数据库转成非关系型数据库:本人的思路是:把关系型数据库的一个主键设置为行键,其他主键设置为一个列名。和行键一个表的其他数据单独成列。
(2)具体分割如下:把学号作为行键,课程号作为列名,student表的其他数据成列。
代码如下:(自己封装了一个jar包)
Hbase_gao.createTable("SC",new String[]{"name","sex","age","123001","123002","123003"}); Hbase_gao.insertRow("SC", "2015001", "name","", "Zhangsan"); Hbase_gao.insertRow("SC", "2015001", "sex","", "male"); Hbase_gao.insertRow("SC", "2015001", "age", "", "23"); Hbase_gao.insertRow("SC", "2015001", "123001", "cname", "Math"); Hbase_gao.insertRow("SC", "2015001", "123001", "credit", "2.0"); Hbase_gao.insertRow("SC", "2015001", "123001", "score", "86"); Hbase_gao.insertRow("SC", "2015001", "123003", "cname", "English"); Hbase_gao.insertRow("SC", "2015001", "123003", "credit", "3.0"); Hbase_gao.insertRow("SC", "2015001", "123003", "score", "69"); Hbase_gao.insertRow("SC", "2015002", "name","", "Mary"); Hbase_gao.insertRow("SC", "2015002", "sex","", "female"); Hbase_gao.insertRow("SC", "2015002", "age", "", "22"); Hbase_gao.insertRow("SC", "2015002", "123002", "cname", "Computer Science"); Hbase_gao.insertRow("SC", "2015002", "123002", "credit", "5.0"); Hbase_gao.insertRow("SC", "2015002", "123002", "score", "77"); Hbase_gao.insertRow("SC", "2015002", "123003", "cname", "English"); Hbase_gao.insertRow("SC", "2015002", "123003", "credit", "3.0"); Hbase_gao.insertRow("SC", "2015002", "123003", "score", "99"); Hbase_gao.insertRow("SC", "2015003", "name","", "Lisi"); Hbase_gao.insertRow("SC", "2015003", "sex","", "male"); Hbase_gao.insertRow("SC", "2015003", "age", "", "24"); Hbase_gao.insertRow("SC", "2015003", "123001", "cname", "Math"); Hbase_gao.insertRow("SC", "2015003", "123001", "credit", "2.0"); Hbase_gao.insertRow("SC", "2015003", "123001", "score", "98"); Hbase_gao.insertRow("SC", "2015003", "123002", "cname", "Computer Science"); Hbase_gao.insertRow("SC", "2015003", "123002", "credit", "5.0"); Hbase_gao.insertRow("SC", "2015003", "123002", "score", "95");
2. 请编程实现以下功能:
链接语句:
//建立连接 public static void init(){ configuration = HBaseConfiguration.create(); configuration.set("hbase.rootdir","hdfs://自己ip:9000/hbase"); try{ connection = ConnectionFactory.createConnection(configuration); admin = connection.getAdmin(); }catch (IOException e){ e.printStackTrace(); } } //关闭连接 public static void close(){ try{ if(admin != null){ admin.close(); } if(null != connection){ connection.close(); } }catch (IOException e){ e.printStackTrace(); } }
(1)createTable(String tableName, String[] fields)
创建表,参数 tableName 为表的名称,字符串数组 fields 为存储记录各个字段名称的数组。 要求当 HBase 已经存在名为 tableName 的表的时候,先删除原有的表,然后再创建新的表。
* 建表。HBase的表中会有一个系统默认的属性作为主键,主键无需自行创建,默认为put命令操作中表名后第一个数据,因此此处无需创建id列 * @param myTableName 表名 * @param colFamily 列族名 * @throws IOException */ public static void createTable(String myTableName,String[] colFamily) throws IOException { init(); TableName tableName = TableName.valueOf(myTableName); if(admin.tableExists(tableName)){ System.out.println("talbe is exists!");
admin.disableTable(tablename);
admin.deleteTable(tablename);
} HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName); for(String str:colFamily){ HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str); hTableDescriptor.addFamily(hColumnDescriptor); admin.createTable(hTableDescriptor); System.out.println("create table success"); } close(); }
(2)addRecord(String tableName, String row, String[] fields, String[] values)
向表 tableName、行 row(用 S_Name 表示)和字符串数组 fields 指定的单元格中添加对 应的数据 values。其中,fields 中每个元素如果对应的列族下还有相应的列限定符的话,用 “columnFamily:column”表示。例如,同时向“Math”、“Computer Science”、“English”三列添加 成绩时,字符串数组 fields 为{“Score:Math”, ”Score:Computer Science”, ”Score:English”},数组 values 存储这三门课的成绩。
* 向某一行的某一列插入数据 * @param tableName 表名 * @param rowKey 行键 * @param colFamily 列族名 * @param col 列名(如果其列族下没有子列,此参数可为空) * @param val 值 * @throws IOException */ public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException { init(); Table table = connection.getTable(TableName.valueOf(tableName)); Put put = new Put(rowKey.getBytes()); put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes()); table.put(put); table.close(); close(); }
(3)scanColumn(String tableName, String column)
浏览表 tableName 某一列的数据,如果某一行记录中该列数据不存在,则返回 null。要求 当参数 column 为某一列族名称时,如果底下有若干个列限定符,则要列出每个列限定符代表 的列的数据;当参数 column 为某一列具体名称(例如“Score:Math”)时,只需要列出该列的 数据。
/** * 根据行键rowkey查找数据 * @param tableName 表名 * @param rowKey 行键 * @param colFamily 列族名 * @param col 列名 * @throws IOException */ public static void getData(String tableName,String rowKey,String colFamily,String col)throws IOException{ init(); Table table = connection.getTable(TableName.valueOf(tableName)); Get get = new Get(rowKey.getBytes()); get.addColumn(colFamily.getBytes(),col.getBytes()); Result result = table.get(get); showCell(result); table.close(); close(); }
(4)modifyData(String tableName, String row, String column)
修改表 tableName,行 row(可以用学生姓名 S_Name 表示),列 column 指定的单元格的 数据。
* 向某一行的某一列插入数据 * @param tableName 表名 * @param rowKey 行键 * @param column 列族名 * @param val 值 * @throws IOException */ public static void modiyData(String tableName,String row,String column,String val) throws IOException { init(); Table table = connection.getTable(TableName.valueOf(tableName)); Put put = new Put(row.getBytes()); put.addColumn(column.getBytes(), val.getBytes()); table.put(put); table.close(); close(); }
(5)deleteRow(String tableName, String row)
删除表 tableName 中 row 指定的行的记录。
/** * 删除数据 * @param tableName 表名 * @param row 行键 * @throws IOException */ public static void deleteRow(String tableName,String row) throws IOException { init(); Table table = connection.getTable(TableName.valueOf(tableName)); Delete delete = new Delete(row.getBytes()); table.delete(delete); table.close(); close(); }