1 apache-phoenix-5.0.0-HBase-2.0安装与简单使用
HBase版本:hbase-2.0.5
官网地址:https://hbase.apache.org/
Phoenix版本:phoenix-5.0.0-HBase-2.0
Phoenix官网地址:http://phoenix.apache.org/download.html
Phoenix安装文档:http://phoenix.apache.org/installation.html
注意:hbase的版本一定要与phoenix的版本保持一致,否则运行报错
安装步骤:
1 解压下载之后的版本,放到指定的目录下
2 复制phoenix安装目录下的phoenix-core-5.0.0-HBase-2.0.jar
和phoenix-5.0.0-HBase-2.0-server.jar
到各个hbase节点的lib 目录下
cp phoenix-core-5.0.0-HBase-2.0.jar phoenix-5.0.0-HBase-2.0-server.jar /hbase/lib
使用scp或者sync命令同步到其他hbase节点
此步骤需要注意:不要将phoenix-5.0.0-HBase-2.0-client.jar的包放到/hbase/lib目录,会报错,提示java.lang.NoSuchMethodError: com.ctc.wstx.stax.WstxInputFactory.createSR
;具体报错信息如下:
3 编辑环境变量
vim /etc/profile.d/my_env.sh
复制如下到环境变量中
#phoenix
export PHOENIX_HOME=/home/hadoop/app/apache-phoenix-5.0.0-HBase-2.0-bin
export PATH=$PATH:$PHOENIX_HOME/bin
使环境变量生效
source /etc/profile.d/my_env.sh
4 测试是否生效
bin/sqlline.py hadoop101,hadoop102,hadoop103:2181
问题:如果运行bin/sqlline.py一直处于卡住状态,则修改PHOENIX_HOME/bin/log4j.properties
psql.root.logger=DEBUG,console,DRFA
log4j.threshold=DEBUG
查看具体的日志信息,获取具体问题,在针对性的进行解决
我的启动时报错如下:
Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException(org.apache.hadoop.hbase.NotServingRegionException): org.apache.hadoop.hbase.NotServingRegionException: hbase:meta,,1 is not online on hadoop102,16020,1603519584313
则进入到Zookeeper的客户端执行如下命令
bin/zkCli.sh
deleteall /hbase
quit
hadoop dfs -rm -r -skipTrash /hbase
是由于我重新安装了Hbase导致的,未及时的清理之前hbase残留信息
https://www.cnblogs.com/kekukekro/p/6339587.html
2 Phoenix操作
2.1 Phoenix Shell
2.1.1表的操作
- 1 显示所有表
!table或!tables
- 2 创建表
直接指定单个列作为RowKey
create table if not exists student(
id varchar primary key,
name varchar);
在Phoenix中,表名和字段会自动转换为大写;如果要小写,使用双引号,如"student"
指定多个列的联合作为RowKey
create table if not exists us_population(
state char(2) not null,
city varchar not null,
population bigint
constraint my_pk primary key (state,city));
- 3 插入数据
upsert into student values('1001','zhangsan');
在phoenix是没有insert语句的,而是upsert语句;upsert有两种用法,upsert into 和upsert select
upsert into语句:单条插入外部数据
upsert select语句:类似于hive中的insert select 语句,批量插入其它表中的数据
UPSERT INTO US_POPULATION (STATE,CITY,POPULATION) SELECT STATE,CITY,POPULATION FROM AK_POPULATION WHERE POPULATION < 40000;
-
salt_buckets: Salting能够通过预分区(pre-splitting)数据到多个region中来显著提升读写性能
本质是在hbase中,rowkey的byte数组的第一个字节位置设定一个系统生成的byte值,这个byte值是由主键生成rowkey的byte数组做一个哈希算法,计算得来的。Salting之后可以把数据分布到不同的region上,这样有利于phoenix并发的读写操作。关于SaltedTable的说明在 http://phoenix.apache.org/salted.html
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SALT_BUCKETS=16;
SALT_BUCKETS的值范围在(1 ~ 256)
如果我们用Phoenix创建了一个saltedtable,那么向该表中写入数据时,原始的rowkey的前面会被自动地加上一个byte(不同的rowkey会被分配不同的byte),使得连续的rowkeys也能被均匀地分布到多个regions
UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.1','S1'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.2','S2'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.3','S3'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.4','S4'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.5','S5'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.6','S6'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.7','S7'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.8','S8'); UPSERT INTO TEST (HOST,DESCRIPTION) values ('192.168.0.9','S9');
此时可以看到,在每个rowkey前面都加了一个byte,也正因为时添加了一个byte,所以salt_buckets的值范围必须在1-256之间
因此,在使用SALT_BUCKETS的时候必须注意以下两点:
-
创建salted table 后,应该使用Phoenix SQL来读写数据,不能使用PhoenixSQL和HBaseAPI
-
如果通过Phoenix创建了一个salted table,只有通过Phoenix SQL插入数据才能使得被插入的原始rowkey前面被自动加上一个byte,通过HBase shell插入数据无法实现
-
Pre-Split(预分区)
Salting能够自动的设置表预分区,但是你得去控制表是如何分区的,所以在建phoenix表时,可以精确的指定要根据什么值来做预分区,比如:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SPLIT ON ('CS','EU','NA');
-
使用多列族
列族包含相关的数据都在独立的文件中,在Phoenix设置多个列族可以提高查询性能
CREATE TABLE TEST (MYKEY VARCHAR NOT NULL PRIMARY KEY, A.COL1 VARCHAR,A.COL2 VARCHAR, B.COL3 VARCHAR);
-
在数据量大的表上使用压缩算法来提高性能
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) COMPRESSION='Snappy';
2.1.2 表的映射
- 1 表的关系
默认情况下,直接在HBase中创建的表,通过Phoenix是查看不到的。如果要在Phoenix中操作HBase中创建的表,则需要在Phoenix中进行表的映射,映射方式有两种:视图映射和表映射 - 2 命令行中创建表test
HBase 中test的表结构如下,两个列族info1、info2。
Rowkey info1 info2
id name address - 3 视图映射
Phoenix创建的视图映射是只读的,所以只能用来做查询,无法通过视图对源数据进行修改等操作。在Phoenix中创建关联test表的视图
create view "test"(id varchar primary key,"info1"."name" varchar, "info2"."address" varchar);
删除视图
drop view "test";
- 4 表映射
使用Phoenix创建对HBase表映射,有两种方法:- 1 HBase中不存在表的时候,可以直接使用create table指令创建所需要的表,系统会自动在Phoenix和HBase中创建对应的表,并会根据指定内的参数对表结构进行初始化
- 2 当HBase中已经存在表的时候,可以以类似创建视图的方式创建关联表,只需要将create view 改为create table 并在最后面加上 column_encoded_bytes=0 即可;
create table "test"(id varchar primary key,"info1"."name" varchar, "info2"."address" varchar) column_encoded_bytes=0;
2.1.3 Phoenix JDBC操作
<dependencies>
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.8.4</version>
</dependency>
</dependencies>
public class PhoenixTest {
public static void main(String[] args) throws Exception {
// 1 定义参数
String driver = "org.apache.phoenix.jdbc.PhoenixDriver";
String url = "jdbc:phoenix:hadoop101,hadoop102,hadoop103:2181";
//2 加载驱动
Class.forName(driver);
//3 创建连接
Connection conn = DriverManager.getConnection(url);
//4 预编译SQL
PreparedStatement pstm = conn.prepareStatement("select * from test");
//5 查询获取返回值
ResultSet rs = pstm.executeQuery();
//6 打印结果
while (rs.next()){
System.out.println(rs.getString(1)+rs.getString(2));
}
//7 关闭资源
rs.close();
pstm.close();
conn.close();
}
}
2.2 创建二级索引
1 添加如下配置到HBase的HRegionServer节点的hbase-site.xml
<!-- phoenix regionserver 配置参数-->
<property>
<name>hbase.regionserver.wal.codec</name>
<value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
<property>
<name>hbase.region.server.rpc.scheduler.factory.class</name> <value>org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory</value>
<description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<property>
<name>hbase.rpc.controllerfactory.class</name>
<value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value>
<description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
2 添加如下配置到HBase中的HMaster节点的hbase-site.xml
<!-- phoenix master 配置参数 -->
<property>
<name>hbase.master.loadbalancer.class</name>
<value>org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.phoenix.hbase.index.master.IndexMasterObserver</value>
</property>
2.2.1 全局二级索引
Global Index是默认的索引格式,创建全局索引时,会在HBase中建立一张新表。也就是说索引数据和数据表是存放在不同的表中的,因此全局索引适用于读多写少的业务场景。
写数据的时候会消耗大量开销,因为索引表也要更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。
在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。
- 1 创建单个字段的全局索引
create table stu(id varchar primary key,name varchar,sex varchar);
upsert into stu values('1001','zhangsan','male');
create index stu_index_name on stu(name);
CREATE INDEX my_index ON my_table (my_col);
1 全局二级索引:会单独写创建一张索引表,RowKey设计方案为:
二级索引字段1+"\x00"+二级索引字段2(复合索引)…+"\x00"+原表rowkey
2 查询的时候 会直接定位到索引表,通过RowKey查到位置,然后从索引表中获取数据
3 读的时候直接从索引表中获取数据,写的时候需要额外往索引表中添加数据,所以这种索引适合读多写少的场景(读快 写少);
创建的索引生效,结果如下:
如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。
- 2 创建携带其他字段的全局索引
CREATE INDEX stu_index_name_sex ON stu(name) INCLUDE (sex);
CREATE INDEX my_index ON my_table (v1) INCLUDE (v2);
索引生效如下图所示:
总结:全局索引要能生效,要求 查询的字段和过滤的字段都要在索引表中存在
2.2.2 本地二级索引
Local Index适用于写操作频繁的场景。
索引数据和数据表的数据是存放在同一张表中(且是同一个Region),避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升。
bin/hbase shell
create 'stu2','INFO',SPLITS=>['a','b','c']
put 'stu2','1001','INFO:NAME','zhangsan'
phoenix shell 执行如下命令
create table "stu2"(id varchar primary key,info.name varchar,info.sex varchar) column_encoded_bytes=0;create local index stu2_index_name on "stu2"(name);create local index stu2_index_name on "stu2"(name);
CREATE LOCAL INDEX my_index ON my_table (my_column);
本地二级索引的RowKey是:
1 原数据region的start key+"\x00"+二级索引字段1+"\x00"+二级索引字段2(复合索引)…+"\x00"+原rowkey
原数据region的start key 保证原始数据和索引数据在同一个Region上,定位到二级索引后根据原RowKey就可以很快的在当前Region上获取到相关信息,从而减少了网络开销和检索成本。
2 查询的时候,会在不同的Region里面分别对二级索引字段定位,查到原RowKey后在本Region上获取其他信息
3 因为这种索引方式只写索引数据,减少了空间的占用,根据索引信息拿到原RowKey,再根据原RowKey到原数据里面获取到其他信息(扫描了两次),所以这种索引适合写多读少的场景(写快 读慢)。
1 Phoenix不建议使用连接池进行操作,详见:https://phoenix.apache.org/faq.html#Is_there_a_way_to_bulk_load_in_Phoenix
2 Phoenix中插入语句(upsert语句)并不会像传统数据库一样存在重复数据,因为Phoenix是建立在Hbase之上,由于HBase的主键设计,相同rowkey的内容可以直接覆盖,这就变相的更新了数据
3 Spark操作Phoenix的注意事项:
-
在使用RDD保存数据到Phoenix的时候,要严格按照Phoenix列名的大小写来输入
-
使用DataFrame保存的时候,对数据源的列名大小写无要求。但是必须保证Phoenix的表列名必须是大写的
-
用Phoenix创建表的时候,除非是已经存在了HBase的表,否则无需要建表的时候对列带引号,这样sql中即使是小写的列也会保存为大写,比如
-创建的Phoenix表名必须和HBase表名一致 CREATE TABLE STUDENT3 ( --这句话直接写就可以了,这样的话,HBase中的RowKey转换成phoenix中的主键,列名就叫自取。 --rowkey自动会和primary key进行对应。 ID VARCHAR NOT NULL PRIMARY KEY , --将名为cf1的列族下,字段名为name的字段,写在这里。 cf1.name VARCHAR , --下面就以此类推 cf1.age VARCHAR , cf2.score VARCHAR )
3 Squirrel 客户端工具连接Phoenix
Squirrel 官网地址:http://www.squirrelsql.org/
第一步:配置Driver,如下图所示
Name:phoenix(可以填写其他名称)
ExampleURL:填写HBase集群的zookeeper集群的连接信息,这里是jdbc:phoenix:192.168.187.128,192.168.187.129,192.168.187.130:2181
Website URL:这里不填写
Java Class Path:选择phoenix-4.2.2-client.jar(是否选中无所谓,只要在Java Class Path里面就行)
Class Name:org.apache.phoenix.jdbc.PhoenixDriver
第二步:配置Aliases,如下图所示:
Name:phoenix(可以填写其他名称)
Driver:选择phoenix,即上一步创建的Driver
URL:这里就是HBase集群的zookeeper的连接ip和port
User Name:可不填写
Password:可不填写
选择Test可以进行连接测试:测试成功之后再点击OK按钮连接集群
第三步:在Aliases标签中双击刚刚创建的phoenix打开连接
点击SQL标签列进行sql命令行界面
编写SQL语句并执行
虚拟机采用静态ip后,无法ping通百度的解决方案:
sudo vim /etc/resolv.conf
添加如下地址或者其中一个即可
nameserver 114.114.114.114
nameserver 8.8.8.8
nameserver 1.1.1.1