Apache Phoenix让Hadoop中支持低延迟OLTP和业务操作分析。
Apache Phoenix可以很好地与其他的Hadoop组件整合在一起,例如:Spark、Hive、Flume以及MapReduce。
sql:结构化查询语言
acid:原子性、一致性、独立性和持久性
上述两张图是从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有很大的优势。
tar xzvf phoenix-hbase-2.4-5.1.2-bin.tar.gz -C ../servers/
<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>
cp /export/servers/phoenix-hbase-2.4-5.1.2-bin/phoenix-server-hbase-2.4-5.1.2.jar .
scp phoenix-server-hbase-2.4-5.1.2.jar hadoop02:/export/servers/hbase-2.4.10/lib/
scp phoenix-server-hbase-2.4-5.1.2.jar hadoop03:/export/servers/hbase-2.4.10/lib/
cp phoenix-client-hbase-2.4-5.1.2.jar bin/
scp conf/hbase-site.xml hadoop02:$PWD/conf
scp conf/hbase-site.xml hadoop03:$PWD/conf
cp /export/servers/hbase-2.4.10/conf/hbase-site.xml .
cd /export/servers/phoenix-hbase-2.4-5.1.2-bin
bin/sqlline.py hadoop01:2181
使用之前的订单数据,但是用phoenix来创建表,并进行数据的增删改查操作。
create table if not exists 表名(
rowkey 名称 类型primary key,
列簇.列名 类型,
……
);
先用VS Code之类的编辑工具,写好创建表的语句
create table if not exists ORDER_DETAIL(
ID varchar primary key,
C1.STATIS varchar,
C1.PAY_MONEY float,
C1.PAY_WAY integer,
C1.USER_ID varchar,
C1.OPERATION_DATE varchar,
C1.CATEGORY varchar
);
再复制到phoenix的客户端运行
进行查看
在hbase的web UI界面查看刚创建的表
同时也可以看到表默认只有一个分区region,也就是没有分区
!desc ORDER_DETAIL
drop table if exists 表名;
drop table if exists ORDER_DETAIL;
在phoenix中,插入数据并不是insert,而是upsert,相当于insert+update,与hbase shell中的put相对应。如果不存在则插入,否则更新
upsert into ORDER_DETAIL1(列簇名.列名,……) values (值1,值2,……);
upsert into ORDER_DETAIL1 values ('000001','已提交',3050,1,'494419','2020-04-25 12:09:30','手机');
与标准的sql一样,phoenix也是用select实现数据的查询
select * from 表名;
select * from ORDER_DETAIL;
在phoenix中,更新数据也是用upsert
upsert into 表名(列名,列簇名.列名,……) values(值1,值2,……);
upsert into ORDER_DETAIL(ID,C1.STATUS) values ('000001','已付款');
在phoenix中,删除数据与标准的sql一样,也是用delete from实现数据的删除
delete from 表名 where rowkey列名=值;
delete from ORDER_DETAIL where ID='000002';
语法:
create_namespace 命名空间名
语法:
list_namespace
describe_namespace 命名空间名
语法:
drop_namespace 命名空间名
注意:
删除命名空间时,在该命名空间下必须没有表,否则无法删除
语法:
create "命名空间名:表名","列簇名"
create "shop:goods","C1"
注意:
使用带有命名空间的表,使用冒号将命名空间和表名连接在一起
语法:
put "命名空间名:表名","rowkey","列簇:列名",值
put "shop:goods","000001","C1:price",5800
版本数一般设计为1
一般情况下,如果对数据不做修改,只保留一个版本,可以节省大量的存储空间
hbase默认创建的表是不进行数据压缩的,进行数据压缩可以节省大量的存储空间,hbase可以使用多种数据压缩编码,包括LZO、SNAPPY、GZIP。
在HBase可以使用多种压缩编码,包括LZO、SNAPPY、GZIP。只在硬盘压缩,内存中或者网络传输中没有压缩。
hbase创建的表默认是没有数据压缩的
语法:
create "命名空间名:表名",{NAME => '列簇名', COMPRESSION => '压缩算法名'}
示例:
create "shop:orders",{NAME => 'C1', COMPRESSION => 'GZ'}
语法:
alter "命名空间名:表名",{NAME => '列簇名', COMPRESSION => '压缩算法名'}
示例
alter "shop:goods",{NAME => 'C1', COMPRESSION => 'GZ'}
如果ROWKEY设计的都是按照顺序递增(例如:时间戳),这样会有很多的数据写入时,负载都在一台机器上。我们尽量应当将写入大压力均衡到各个RegionServer
long类型为8个字节,8个字节可以保存非常大的无符号整数,例如:18446744073709551615。如果是字符串,是按照一个字节一个字符方式保存,需要快3倍的字节数存储。
默认情况下,一个hbase表只有一个分区(region),被托管在一个RegionServer中
每个region有两个重要的属性:start key和end key,标识这个region维护的rowkey的范围。如果只有一个region,这它们都为空,没有边界。所有的数据都会存放在这个region中。但数据很大的时候,会将region通过去一个mid key来分成两个region。
预分区的个数=节点的倍数,如果有三个节点,则预分区的个数为6。
默认region的大小为10G,假如进行预估接下来的一年时间数据的大小为10T,则需要的预分区数=10*1000G/10G=1000个region。
语法:
create "test:t1",'C1',SPLITS=>['10','20','30','40']
create "test:t2","C1",{NUMREGIONS=>6,SPLITALGO=>'HexStringSplit'}
一般按照数据量来预估或者根据节点数的倍数来设定
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会根据rowkey建立索引,来提供查询的速度,这样的索引叫做一级索引。如果根据name进行查询,因为没有根据name建立索引,所以查询效率比较低,这是可以给name来创建二级索引。
语法:
create index 索引名称 on 表名(列名1,列名2……);
举例:
create index idxname on ORDER_DETAIL(CATEGORY);
注意:
Phoenix中的索引,其实底层还是Hbase的表结构,这些索引表是专门用来加快查询速度。
注意:创建表的时候指定了SALT_BUCKETS,是不支持本地索引的。
CREATE local INDEX 索引名称 ON 表名 (列名1, 列名2, 列名3...)
可以不需要在找到索引条目后返回到主表中,可以将关心的数据捆绑在索引行中,从而节省了读取的时间开销。
创建语法:
create index 索引名称 on 表名(列名1,列名2……) include(列名3);
create index idxcombo on ORDER_DETAIL1(CATEGORY,STATIS,PAY_MONEY) include(USER_ID);
scan "IDXCOMBO",{FORMATTER=>'toString'}
适用于高版本的phoenix,可以基于任意表达式(函数)创建索引
语法
create index 索引名称 on 表名(函数名(列名1),列名2……);
create index idxsuerid on ORDER_DETAIL1(C1.USER_ID) include(ID,C1.PAY_MONEY);
select USER_ID,ID,PAY_MONEY from ORDER_DETAIL1 where USER_ID="494419";
drop index 索引名 on 表名
drop index IDXCOMBO on ORDER_DETAIL1;