分布式数据库原理与应用-4 HBase


第三章 Hbase

05 Hbase过滤器

1
2
可以根据主键、列簇、列、版本等更多的条件来对数据进行过滤。
类似SQL中的WHERE
1
2
hbase(main):011:0> show_filters
DependentColumnFilter KeyOnlyFilter ColumnCountGetFilter SingleColumnValueFilter PrefixFilter SingleColumnValueExcludeFilter FirstKeyOnlyFilter ColumnRangeFilter TimestampsFilter FamilyFilter QualifierFilter ColumnPrefixFilter RowFilter MultipleColumnPrefixFilter InclusiveStopFilter PageFilter ValueFilter ColumnPaginationFilter
1
2
3
过滤器语法格式:

scan/get ‘表名’,{Filter => “过滤器 ( 比较运算符,’比较器’)”}

image-20230418213720968

RowFilter

1
2
3
4
5
6
7
RowFilter:针对rowkey进行字符串的比较过滤器。

举例:
例1:显示行键包含0的键值对;
scan 'student',{FILTER=>"RowFilter(=,'substring:0’)”}
例2:显示行键字节顺序大于002的键值对;
scan 'student',FILTER=>"RowFilter(>,'binary:002')"

PrefixFilter

1
2
3
4
5
6
PrefixFilter:rowkey前缀比较器,一种更简单的比较行键前缀的命令,等值比较。
举例:

例1:显示行键前缀为0开头的键值对;
scan 'student',{FILTER=>"RowFilter(=,'substring:0’)”}
scan 'student',FILTER=>"PrefixFilter('003')"

KeyOnlyFilter

1
2
KeyOnlyFilter:
只对cell的键进行过滤和显示,但不显示值。

image-20230418214240115

FirstKeyOnlyFilter

1
2
3
4
5
6
7
8
9
10
11
FirstKeyOnlyFilter:只扫描相同键的第一个cell,其键值对都会显示出来。

例4:统计表的逻辑行数;
count 'student’
scan 'student',FILTER=>"FirstKeyOnlyFilter()"

hbase(main):008:0> scan 'student', FILTER=>"FirstKeyOnlyFilter()"
ROW COLUMN+CELL 001 column=grades:englisg, timestamp=1541485306878, value=80
002 column=grades:bigdata, timestamp=1541485403649, value=88
003 column=grades:bigdata, timestamp=1541485412686, value=80
3 row(s) in 0.0400 seconds

InclusiveStopFilter

1
2
InclusiveStopFilter:替代ENDROW返回终止条件行;
例5:显示起始行键为001,结束行为003的记录;

image-20230418214950938

总结

image-20230418215313360

FamilyFilter

1
2
3
4
5
FamilyFilter:针对列族进行比较和过滤。

例1:显示列族前缀为stu开头的键值对;
scan 'student',FILTER=>"FamilyFilter(=,'substring:stu’)”
scan 'student',FILTER=>"FamilyFilter(=,‘binary:stu’)”

image-20230418215532681

QualifierFilter

1
2
3
4
QualifierFilter:列标识过滤器。

例2:显示列名为name的记录;
scan 'student',FILTER=>"QualifierFilter(=,'substring:name')"

image-20230418220036827

ColumnPrefixFilter

1
2
3
4
5
ColumnPrefixFilter:对列名前缀进行过滤。
例2:显示列名为name的记录;
scan 'student',FILTER=>"ColumnPrefixFilter('name’)”

等价于scan 'student',FILTER=>"QualifierFilter(=,'substring:name')
1
MultipleColumnPrefixFilter:可以指定多个前缀
1
2
例3:显示列名为name和age的记录;
scan 'student',FILTER=>"MultipleColumnPrefixFilter('name','age')"

ColumnRangeFilter

1
2
3
ColumnRangeFilter :设置范围按字典序对列名进行过滤;
例4:查询列名在bi和na之间的记录
Student表中有以下列族和列名

image-20230418220523574

TimestampsFilter

1
2
3
4
TimestampsFilter :时间戳过滤器。支持等值方式比较,但可以设置多个时间戳

例5:只查询时间戳为1和2的键值对;
scan 'student',FILTER=>"TimestampsFilter(2,4)"
1
2
hbase(main):030:0> scan 'student',FILTER=>"TimestampsFilter(2,4)"
ROW COLUMN+CELL 004 column=stuinfo:age, timestamp=2, value=19 004 column=stuinfo:name, timestamp=2, value=curry 004 column=stuinfo:sex, timestamp=4, value=male 1 row(s) in 0.0150 seconds

ValueFilter

1
2
3
4
5
ValueFilter :值过滤器。

例6:查询值等于19的所有键值对
scan 'student',FILTER=>"ValueFilter(=,'binary:19’)”
scan 'student',FILTER=>"ValueFilter(=,'substring:19')"

SingleColumnValueFilter

1
2
3
4
5
6
7
SingleColumnValueFilter:在指定的列族和列中进行值过滤器。
例7:查询stuinfo列族age列中值等于19的所有键值对

scan 'student',{COLUMN=>'stuinfo:age’,
FILTER=>"SingleColumnValueFilter('stuinfo','age',=,'binary:19')"}

SingleColumnValueExcludeFilter:在指定的列族和列中进行值过滤器,与SingleColumnValueFilter功能相反。

ColumnCountGetFilter

1
2
3
4
5
ColumnCountGetFilter:限制每个逻辑行返回的键值对数
例7:返回行键为001的前3个键值对

hbase(main):004:0> get 'student', '001',FILTER=>"ColumnCountGetFilter(3)"
COLUMN CELL grades:englisg timestamp=1541485306878, value=80 grades:math timestamp=1541485384199, value=90 stuinfo:age timestamp=1541485224974, value=18 3 row(s) in 0.0950 seconds

PageFilter

1
2
3
4
5
6
7
8
9
PageFilter :基于行的分页过滤器,设置返回行数。

hbase(main):005:0> scan 'student',FILTER=>"PageFilter(1)"
ROW COLUMN+CELL 001 column=grades:englisg, timestamp=1541485306878, value=80
001 column=grades:math, timestamp=1541485384199, value=90
001 column=stuinfo:age, timestamp=1541485224974, value=18
001 column=stuinfo:name, timestamp=1541485170696, value=alice
001 column=stuinfo:sex, timestamp=1541485235855, value=female
1 row(s) in 0.0680 seconds

ColumnPaginationFilter

1
2
3
ColumnPaginationFilter:基于列的进行分页过滤器,需要设置偏移量与返回数量 。

例9:显示每行第1列之后的2个键值对。
1
2
hbase(main):006:0> scan 'student'
ROW COLUMN+CELL 001 column=grades:englisg, timestamp=1541485306878, value=80 001 column=grades:math, timestamp=1541485384199, value=90 001 column=stuinfo:age, timestamp=1541485224974, value=18 001 column=stuinfo:name, timestamp=1541485170696, value=alice 001 column=stuinfo:sex, timestamp=1541485235855, value=female 002 column=grades:bigdata, timestamp=1541485403649, value=88 002 column=grades:englisg, timestamp=1541485319132, value=85 002 column=grades:math, timestamp=1541485376414, value=78 002 column=stuinfo:class, timestamp=1541485278646, value=1802 002 column=stuinfo:name, timestamp=1541485187403, value=nancy 002 column=stuinfo:sex, timestamp=1541485245291, value=male
1
2
3
hbase(main):007:0> scan 'student',FILTER=>"ColumnPaginationFilter(2,1)"
ROW COLUMN+CELL 001 column=grades:math, timestamp=1541485384199, value=90 001 column=stuinfo:age, timestamp=1541485224974, value=18 002 column=grades:englisg, timestamp=1541485319132, value=85 002 column=grades:math, timestamp=1541485376414, value=78 003 column=grades:englisg, timestamp=1541485328260, value=90 003 column=grades:math, timestamp=1541485368087, value=80 004 column=stuinfo:name, timestamp=2, value=curry 004 column=stuinfo:sex, timestamp=4, value=male
4 row(s) in 0.0840 seconds
1
2
003                      column=grades:bigdata, timestamp=1541485412686, value=80       003                      column=grades:englisg, timestamp=1541485328260, value=90       003                      column=grades:math, timestamp=1541485368087, value=80           003                      column=stuinfo:age, timestamp=1541485209410, value=19           003                      column=stuinfo:class, timestamp=1541485271479, value=1803       003                      column=stuinfo:name, timestamp=1541485198223, value=harry       003                      column=stuinfo:sex, timestamp=1541485253075, value=male         004                      column=stuinfo:age, timestamp=2, value=19                       004                      column=stuinfo:name, timestamp=2, value=curry                   004                      column=stuinfo:sex, timestamp=4, value=male                              
4 row(s) in 0.0980 seconds

组合使用过滤器

1
组合使用过滤器:使用AND或OR等连接符,组合多个过滤器进行组合扫描。
1
2
3
4
5
6
7
8
例10:组合过滤器的使用
hbase(main):008:0> scan 'student',FILTER=>"ColumnPaginationFilter(2,1) AND ValueFilter(=,'substring:ma')"
ROW COLUMN+CELL
004 column=stuinfo:sex, timestamp=4, value=male
1 row(s) in 0.1040 seconds
hbase(main):010:0> scan 'student',FILTER=>"ColumnPaginationFilter(1,1) OR ValueFilter(=,'substring:ma')"
ROW COLUMN+CELL 001 column=grades:math, timestamp=1541485384199, value=90 001 column=stuinfo:sex, timestamp=1541485235855, value=female 002 column=grades:englisg, timestamp=1541485319132, value=85 002 column=stuinfo:sex, timestamp=1541485245291, value=male 003 column=grades:englisg, timestamp=1541485328260, value=90 003 column=stuinfo:sex, timestamp=1541485253075, value=male 004 column=stuinfo:name, timestamp=2, value=curry 004 column=stuinfo:sex, timestamp=4, value=male
4 row(s) in 0.0440 seconds

总结

1
2
3
4
5
6
7
8
9
10
11
12
FamilyFilter:针对列族进行比较和过滤。
QualifierFilter:列标识过滤器。
ColumnPrefixFilter:对列名前缀进行过滤。
MultipleColumnPrefixFilter:可以指定多个前缀
ColumnRangeFilter :设置范围按字典序对列名进行过滤;
TimestampsFilter :时间戳过滤器。支持等值方式比较,但可以设置多个时间戳
ValueFilter :值过滤器。
SingleColumnValueFilter :在指定的列族和列中进行值过滤器。
SingleColumnValueExcludeFilter:在指定的列族和列中进行值过滤器,与SingleColumnValueFilter功能相反。
ColumnCountGetFilter :限制每个逻辑行返回的键值对数
PageFilter :基于行的分页过滤器,设置返回行数。
ColumnPaginationFilter :基于列的进行分页过滤器,需要设置偏移量与返回数量 。

06 Hbase Java编程方法

image-20230418223225014

1
2
3
4
5
6
首先介绍基于JAVA的编程方法,HBase是基于java语言开发,用户可以利用包含java语言在内的多种语言进行调用开发。由于java是原生语言,因此利用java进行应用开发,以及过滤器等内容的开发最为方便。

HBase对java开发环境并无特殊要求,只要将用到的HBase的库包加入引用路径即可。
本节讲述以eclipse为java的集成开发环境,具体步骤如下:
首先在eclipse中建立标准的java工程,给工程命名为hbase,其他使用默认配置,按步骤完成项目的创建。
然后打开hbase项目的属性(对应图中序号1),选择java构建路径标签页(2),选择库(3),点击添加外部jar按钮(4)。然后弹出框会让你选择hbase安装目录下的lib。将需要的包导入工程,导入成功后会在工程里引用的库中出现你所选择的jar包。(解说完后播放操作视频hbase_java环境配置.mp4)

包导入

1
2
3
4
5
6
7
8
9
10
11
12
使用Hadoop和HBase的环境配置
import org.apache.hadoop.conf.Configuration;

HBase的客户端接口
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;

HBase工具包
import org.apache.hadoop.hbase.util.Bytes;

HBase过滤器
import org.apache.hadoop.hbase.filter.*;
1
2
3
工程目录src下新建类文件,在java文件中import需要的HBase包,比如HBase的环境配置包需要导入Configuration包(对应显示红色)
HBase客户端接口需要导入hbase.client(绿色两行)
工具包需要导入hbase.util.Bytes(蓝色),而如果使用过滤器需要导入hbase.filter包。如果还需要其他包可以从hbase lib里去寻找,并导入工程即可。

建立连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static Configuration conf;
public static Connection connection;
public static Admin admin;

public void getconnect() throws IOException
{
conf=HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "cm-cdh01");
conf.set("hbase.zookeeper.property.clientPort", "2181");
try{
connection=ConnectionFactory.createConnection(conf);
admin=connection.getAdmin();
}
catch(IOException e){
e.printStackTrace();
}
}
1
2
3
环境配置好后,接下来开始连接数据库,在分布式环境下,客户端访问HBase需要通过ZooKeeper的地址和端口来获取当前活跃的Master和所需的RegionServer地址,
首先建立三个全局变量,conf、connection和admin(高亮显示红色字体),conf用来描述zookeeper集群的访问地址,connect用来建立连接,admin是创建的数据库管理员,执行具体的数据表操作。
Conf使用set方法来设置集群地址和端口号,然后使用ConnectionFactory来建立连接,并让admin获取管理员的操作权限,至此已经java客户端已经连接上hbase数据库。

Admin接口

image-20230418223516389

1
2
3
接下来具体看下HBase API中常用的接口 ,首先是Admin接口,Admin用于管理HBase数据库的表信息,如创建表,用到了createtable,删除表用到disabletable和deletetable,与Hbase中的create,delete和disable命令对应。另外admin接口还可以使用listtables方法列出hbase中所有的表,使用getTableDescriptor来获取表的结构信息,分别于hbase shell中的,list 和describe命令。

注意listtables和getTableDescriptor方法返回的是HTableDescriptor类结构的数据。

创建和删除表

image-20230418223634346

1
2
3
4
5
6
7
8
9
接着通过具体代码来看下Admin接口提供的方法的使用。首先是创建表,在创建表之前用tablesexists来判断表是否存在,注意设定tableName对象的语法,使用valueOf方法设置表名。如果表已经存在则使用disableTable和deleteTable方法来删除表,注意这里与hbaseshell中操作一样,先禁用表再删除表(红框)。

(这一段对应蓝色文字框)HTableDescriptor类用来描述表结构,包括HBase中表格的详细信息,例如表中的列族、该表的类型、是否只读、MemStore的最大空间等,并且提供了一些操作表的方法,比如增加列族addFamliy()、删除列族removeFamily()和设置属性值setValue()等方法。

(这一段对应绿色文字框)HColumnDescriptor类则用来描述列族,比如列族的版本数,压缩设置等。此类通常在添加列族或者创建表的时候使用,一旦列族建立就不能被修改,只有通过删除列族,再创建新的列族来间接修改。HCloumnDescriptor类提供getName()、getValue()和setValue等方法对列族的数据进行操作。

(对应绿色虚线框的内容)这里的代码使用了两种方式创建列族(绿色框),建立stuinfo时(黄色三行),先通过对象HColumnDescriptor自定义列族属性,比如列族名和块大小,然后根据列族属性使用addfamily建立列族。而建立grades列族时(绿色行)直接使用addfamily方法根据默认属性建立的。

描述和建立完列族信息后,通过createTable建立表格。

Table接口

image-20230418223657412

1
再来看下另一个接口Table,如果不需要创建表,直接插入数据,可以不用建立Admin对象,使用Table接口即可。Table接口主要用来进行数据的操作,比如删除指定行使用delete,获取指定行的数据使用get,以及向表中添加数据使用put方法。

Put数据更新

1
2
3
4
5
6
7
8
public static void addData() throws IOException {
Table table = connection.getTable(TableName.valueOf("student"));
Put put = new Put(Bytes.toBytes(“001"));
put.addColumn(Bytes.toBytes("StuInfo"), Bytes.toBytes("name"), Bytes.toBytes(“harry"));
put.addColumn(Bytes.toBytes("StuInfo"), Bytes.toBytes("name"), Bytes.toBytes(“harry"));
table.put(put);
table.close();
}
1
2
3
4
5
6
7
8
Put put1 = new Put(Bytes.toBytes("002"));
put1.addColumn(Bytes.toBytes("StuInfo"), Bytes.toBytes("name"), Bytes.toBytes("jess"));
Put put2 = new Put(Bytes.toBytes("003"));
put2.addColumn(Bytes.toBytes("Grades"), Bytes.toBytes("english"), Bytes.toBytes("98"));
List<Put> putList = new ArrayList<Put>();
putList.add(put1);
putList.add(put2);
table.put(putList);
1
2
3
4
5
首先来看下put方法,put主要用来插入,也可以对已有的记录进行更新,在使用put方法前,需要根据表名建立和它的连接(红色行)

与HBase shell相同,使用put方法可以逐条的插入数据,put对象中首先指明行键为001,并通过addColumn方法加入键值对,addColumn方法的参数分别为列族stuinfo,列name和值harry。这里加入了2个键值对,说明这一行有2列,table.Put方法将put对象写入内存和日志,此时数据已经可以被查出。

另外可以采用链表的方式一次性插入多个键值对,如下图,put1插入1键值对,put2插入1个键值对,然后建立链表putList,使用add方法将两个put对象插入到链表中,最后一次性插入到表中。

查询数据-Get

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void getRow(String tableName, String rowKey) throws IOException {  
Table table = connection.getTable(TableName.valueOf("student"));
Get get = new Get(Bytes.toBytes(rowKey));
Result result = table.get(get);
for (Cell cell : result.rawCells()) {
System.out.println(
"行键:" + new String(CellUtil. getCellKeyAsString(cell)) + "\t" +
"列族:" + new String(CellUtil.cloneFamily(cell)) + "\t" +
"列名:" + new String(CellUtil.cloneQualifier(cell)) + "\t" +
"值:" + new String(CellUtil.cloneValue(cell)) + "\t" +
"时间戳:" + cell.getTimestamp());
}
table.close();
}
1
2
3
插入数据后,可以根据行键进行查询,比如get方法,此代码中,先建立连接,通过get对象描述查询条件,再通过table.get方法进行实际查询(紫色两行)。查询结构写入result中,由于get方法一次获取一个逻辑行,即可能包含多个键值对,因此查询结构通过循环的方法将逐个键值对输出显示。

显示时,getCellKeyAsString用来获取行键,cloneFamily用来获取列族,cloneQualifier用来获取列名,cloneValue获取具体值,getTimestamp获取时间戳

查询数据-Scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void scanTable(String tableName) throws IOException {  
Table table = connection.getTable(TableName.valueOf("student"));
Scan scan = new Scan();
ResultScanner results = table.getScanner(scan);
for (Result result : results) {
for (Cell cell : result.rawCells()) {
System.out.println(
"行键:" + new String(CellUtil.getCellKeyAsString(cell)) + "\t" +
"列族:" + new String(CellUtil.cloneFamily(cell)) + "\t" +
"列名:" + new String(CellUtil.cloneQualifier(cell)) + "\t" +
"值:" + new String(CellUtil.cloneValue(cell)) + "\t" +
"时间戳:" + cell.getTimestamp());
}
}
table.close();
}
1
Scan的操作语法与get类似,都需要建立连接,描述查询条件,再进行实际查询,核心语句是table.getScanner,后续的显示页和之前代码基本相同,但是,由于scan的结果得到的多个逻辑行,且每个逻辑行包含多个键值对,因此采用二层循环的方式来显示每一个键值对的内容,(红框所示)。

删除行和列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Table table = connection.getTable(TableName.valueOf(tableName));

1,删除指定行
Delete delete1 = new Delete(Bytes.toBytes(‘001’));

2,删除指定列族
Delete delete2 = new Delete(Bytes.toBytes(‘002’));
delete2.addFamily(Bytes.toBytes(‘stuinfo’));

3,删除指定列族中的列
Delete delete3 = new Delete(Bytes.toBytes(‘003’));
delete3.addColumn(Bytes.toBytes(‘grades’),Bytes.toBytes(‘math’));

调用 table.delete执行删除
table.delete(delete);
1
2
3
4
5
6
完成了数据的新增和查询,Hbase api也提供删除数据,可以指定行键,列族和列进行删除,
如第一个delete对象只有行键属性,因此会删除一个逻辑行,即所有行键为001的键值对都将被删除;
第二个delete对象通过addfamily方法加入了列族参数stuinfo,因此只会删除再stuinfo列族中,行键为002的键值对;
第三个delete对象通过addColumn方法加入列名参数math,同时也指定了列族grades,因此只会删除行键为003,grades列族中math列的键值对。

最后调用table.delete方法来完成删除。

07 Hbase Python编程方法


本文标题:分布式数据库原理与应用-4 HBase

文章作者:TTYONG

发布时间:2023年04月17日 - 16:04

最后更新:2023年06月22日 - 15:06

原始链接:http://tianyong.fun/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E5%8E%9F%E7%90%86%E4%B8%8E%E5%BA%94%E7%94%A8-4%20HBase.html

许可协议: 转载请保留原文链接及作者。

多少都是爱
0%