全文数据库是全文检索系统的主要构成部分。所谓全文数据库是将一个完整的信息源的全部内容转化为计算机可以识别、处理的信息单元而形成的数据集合。全文数据库不仅存储了信息,而且还有对全文数据进行词、字、段落等更深层次的编辑、加工的功能,而且所有全文数据库无一不是海量信息数据库。
Phoenix官方网址:http://phoenix.apache.org/
Apache Phoenix可以很好地与其他的Hadoop组件整合在一起,例如:Spark、Hive、Flume以及MapReduce。
链接:https://phoenix.apache.org/who_is_using.html
链接:https://phoenix.apache.org/performance.html
上述两张图是从Phoenix官网拿下来的,这容易引起一个歧义。就是:有了HBase + Phoenix,那是不是意味着,我们将来做数仓(OLAP)就可以不用Hadoop + Hive了?
千万不要这么以为,HBase + Phoenix是否适合做OLAP取决于HBase的定位。Phoenix只是在HBase之上构建了SQL查询引擎(注意:我称为SQL查询引擎,并不是像MapReduce、Spark这种大规模数据计算引擎)。HBase的定位是在高性能随机读写,Phoenix可以使用SQL快插查询HBase中的数据,但数据操作底层是必须符合HBase的存储结构,例如:必须要有ROWKEY、必须要有列蔟。因为有这样的一些限制,绝大多数公司不会选择HBase + Phoenix来作为数据仓库的开发。而是用来快速进行海量数据的随机读写。这方面,HBase + Phoenix有很大的优势。
在线分析处理系统,hadoop、hbase、hive提供支持
在线事务处理系统,传统的关系数据库支持
链接:https://phoenix.apache.org/download.html
从官网上下载与HBase版本对应的Phoenix版本。
tar -zxvf phoenix-hbase-2.4.0-5.1.3-bin.tar.gz -C ../servers/
解压文件:
查看:
添加内容如下:
property>
<property>
<name>phoenix.schema.isNamespaceMappingEnabledname>
<value>truevalue>
property>
<property>
<name>hbase.table.sanity.checksname>
<value>falsevalue>
property>
<property>
<name>hbase.coprocessor.abortonerrorname>
<value>falsevalue>
property>
<property>
<name>hbase.regionserver.wal.codecname>
<value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodecvalue>
property>
scp conf/hbase-site.xml hadoop002:$PWD/conf
scp conf/hbase-site.xml hadoop003:$PWD/conf
hadoop001:
cp phoenix-server-hbase-2.4.0-5.1.3.jar /export/servers/hbase-2.4.10/lib/
hadoop002:
scp phoenix-server-hbase-2.4.0-5.1.3.jar hadoop002:/export/servers/hbase-2.4.10/lib/
hadoop003:
scp phoenix-server-hbase-2.4.0-5.1.3.jar hadoop003:/export/servers/hbase-2.4.10/lib/
cp phoenix-client-hbase-2.4.0-5.1.3.jar bin/
cp conf/hbase-site.xml ../phoenix-hbase-2.4.0-5.1.3-bin/bin/
cd ../phoenix-hbase-2.4.0-5.1.3-bin/bin/
bin/sqlline.py hadoop001:2181
说明启动成功
语法:
create table if not exists 表名(
rowkey 名称 类型 primary key,
列簇名.列名 类型,
......
);
在实际操作中,先用vscode之类的编辑工具,写好相关的语句,然后再复制到phoenix中运行
-- 创建表ORDER_1
create table if not exists ORDER_1 (
ID varchar primary key ,
C1.STATUS varchar ,
C1.PAY_MONEY float ,
C1.PAY_WAY integer ,
C1.USER_ID varchar ,
C1.OPERATION_DATE varchar ,
C1.CATEGORY varchar
);
语法:
!desc 表名
语法:
drop table if exists 表名;
drop table if exists ORDER_1;
create table if not exists ORDER_1 (
ID varchar primary key ,
C1.Status varchar ,
C1.PAY_MONEY float ,
C1.PAY_WAY integer ,
C1.user_id varchar ,
C1.OPERATION_DATE varchar ,
C1.category varchar
);
在Phoenix中,插入数据并不是insert,而是upsert,相当于insert和update合起来的缩写,与HBase shell中的put相当于,如果数据存在则修改,如果不存在则插入。
语法:
upsert into 表名(列簇名.列名,...) values(值1,...);
upsert into ORDER_1 values ('000001','已完成',2000,1,'494419','2024-04-20 12:00:30','手机');
与标准的sql一样,在Phoenix中也是用select实现数据的查询
select * from ORDER_1;
在Phoenix中,修改数据也使用upsert
语法:
upsert into 表名(列簇名.列名,...) values(值1,...);
upsert into ORDER_1(ID,C1.STATUS) values('000001','已付款') ;
在Phoenix中,删除数据与标准的sql一样,也是用delete from实现数据的删除
语法:
delete from 表名 where rowkey列名=值;
delete from ORDER_1 where ID = '000001';
类似与mysql和hive中的数据库,对数据进行分类存放,按照业务域来划分类别,这些不同的业务域就叫做命名空间(namespace)。
list_namespace
语法:
create_namespace 命名空间名
create_namespace "network"
语法:
list_namespace
describe_namespace 命名空间名
describe_namespace "network"
语法:
drop_namespace 命名空间名
drop_namespace "network"
注意:
删除命名空间时,必须在该命名空间下没有表,否则无法删除
语法:
create “命名空间名:表名”,”列簇名”
create "network:students","info"
在web ui 上查看:
注意:
使用带有命名空间的表,用冒号将命名空间和表名连起来
语法:
put “命名空间名:表名”,”rowkey”,”列簇名:列名”,值
put "network:students","0001","info:name","张三"
put "network:students","0001","info:age",20
scan "network:students",{FORMATTER=>'toString'}
HBase列蔟的数量应该越少越好,一般情况下,一个表只设计一个列簇
版本数一般设计为1
一般情况下,如果对数据不做修改,只保留一个版本,可以节省大量的存储空间
describe "network:students"
在HBase可以使用多种压缩编码,包括LZO、SNAPPY、GZIP。只在硬盘压缩,内存中或者网络传输中没有压缩。
压缩算法 | 压缩后占比 | 压缩 | 解压缩 |
---|---|---|---|
GZIP | 13.4% | 21 MB/s | 118 MB/s |
LZO | 20.5% | 135 MB/s | 410 MB/s |
Zippy/Snappy | 22.2% | 172 MB/s | 409 MB/s |
根据实际情况,选择合适的压缩算法
HBase中的表默认不适用压缩,进行数据压缩可以节省存储空间
语法:
create "命名空间名:表名",{NAME => '列簇名', COMPRESSION => '压缩算法名'}
示例:
create_namespace "shop"
create "shop:orders",{NAME => 'C1',COMPRESSION => 'GZ'}
describe "shop:orders"
语法:
alter “命名空间名:表名”,{NAME => ‘列簇名’, COMPRESSION => ‘压缩算法名’}
示例
create "shop:goods","C1"
alter "shop:goods",{NAME => 'C1', COMPRESSION => 'GZ'}
如果ROWKEY设计的都是按照顺序递增(例如:时间戳),这样会有很多的数据写入时,负载都在一台机器上。我们尽量应当将写入大压力均衡到各个RegionServer
long类型为8个字节,8个字节可以保存非常大的无符号整数,例如:18446744073709551615。如果是字符串,是按照一个字节一个字符方式保存,需要快3倍的字节数存储。
1.反转策略
如果设计出的ROWKEY在数据分布上不均匀,但ROWKEY尾部的数据却呈现出了良好的随机性,可以考虑将ROWKEY的翻转,或者直接将尾部的bytes提前到ROWKEY的开头。
示例:
182xxxx7890-->0987xxx281
182xxxx6379-->9736xxx281
182xxxx1355-->5531xxx281
20200911145043-->34054111900202
20200911145058-->85054111900202
20200911145501-->10554111900202
优点:实现简单
缺点:反转策略可以使ROWKEY随机分布,但是牺牲了ROWKEY的有序性;利于Get操作,但不利于Scan操作,因为数据在原ROWKEY上的自然顺序已经被打乱
2.加盐策略
在原来的rowkey的前面加上固定长度的随机数,这个随机数就叫做盐,这样使得rowkey具有随机性
优点:rowkey的随机性能保障数据在所有的regionserver之间的负载均衡
缺点:因为添加的是随机数,基于原来的rowkey查询时无法知道随机数是什么,会影响查询速度,不适合数据的读取
3.哈希策略
基于 ROWKEY的完整或部分数据进行 Hash,而后将Hashing后的值完整替换或部分替换原ROWKEY的前缀部分
这里说的 hash 包含 MD5、sha1、sha256 或 sha512 等算法
优点:同加盐策略
缺点:Hashing 也不利于 Scan,因为打乱了原RowKey的自然顺序
语法:
create_namespace "test"
create "test:t1",'C1',SPLITS=>['10','20','30','40']
点击t1表,查看详情
create "test:t2","C1",{NUMREGIONS=>6,SPLITALGO=>'HexStringSplit'}
点击t2查看详情
一般按照数据量来预估或者根据节点数的倍数来设定
Phoenix的视图就是对已经创建的HBase表建立映射关系,从而实现对已有表的快速查询。
语法:
create view if not exists "命名空间名"."表名" (
"Rowkey名" 类型r primary key,
"列簇"."列名" 类型,
"列簇"."列名" 类型
……
);
示例:
create view if not exists "shop"."goods" (
"id" varchar primary key,
"C1"."name" varchar,
"C1"."price" varchar
);
语法:
select * from "命名空间名"."表名" where 条件;
示例:
添加数据(hbase shell):
put "shop:goods","000001","C1:name","冰箱"
put "shop:goods","000001","C1:price",5800
put "shop:goods","000002","C1:name","洗衣机"
put "shop:goods","000002","C1:price",3500
查询:
select * from "shop"."goods";
一般情况下,Hbase会根据rowkey建立索引,来提供查询的速度,这样的索引叫做一级索引。如果根据name进行查询,因为没有根据name建立索引,所以查询效率比较低,这是可以给name来创建二级索引。
语法:
create index 索引名称 on 表名(列名1,列名2……);
举例:
添加数据:
upsert into ORDER_1 values ('000001','已完成',2000,1,'494419','2024-04-20 12:00:30','手机');
upsert into ORDER_1 values ('000002','已付款',6666,1,'494420','2024-04-20 12:00:30','电脑');
创建视图:
create index idxname on ORDER_1(CATEGORY);
注意:Phoenix中的索引,其实底层还是Hbase的表结构,这些索引表是专门用来加快查询速度。
创建语法:
create local index 索引名称 on 表名(列名1,列名2……);
可以不需要在找到索引条目后返回到主表中,可以将关心的数据捆绑在索引行中,从而节省了读取的时间开销。
创建语法:
create index 索引名称 on 表名(列名1,列名2……) include(列名3);
示例:
create index idxcombo on ORDER_1(CATEGORY,STATUS,PAY_MONEY) include(USER_ID);
适用于高版本的phoenix,可以基于任意表达式(函数)创建索引
语法
create index 索引名称 on 表名(函数名(列名1),列名2……);
create index idxsuerid on ORDER_1(C1.USER_ID) include(ID,C1.PAY_MONEY);
select C1.USER_ID,ID,C1.PAY_MONEY from ORDER_1 where C1.USER_ID='494419';
注意:查询的时候还是得加上列簇。
drop index 索引名 on 表名
示例:
drop index IDXCOMBO on ORDER_1;
参考文章:
全文检索
刚搭完HBase集群,Phoenix一启动,HBase就全崩了,是什么原因?
Phoenix映射hbase原表实现
HBase系列(四)、HBase优化之RowKey 设计