Hbase2.0.5-整合Phoenix实际操作

1.Hbase与Mysql区别

1.Mysql 创建表 一般一级索引为主键,二级索引
2.Phoenix 支持创建二级索引,Hbase没有二级索引,默认rowkey设计已实现

2.Phoenix定义

1.Phoenix是HBase的开源SQL皮肤。可以使用标准JDBC API代替HBase客户端API来创建表,插入数据和查询HBase数据。

说明:Phoenix没有内核,内核在使用Hbase的时候为Hbase。

3.使用Phoenix原因

1.为Hbase建立二级索引(最重要原因)
2.标准JDBCAPI代替Hbase客户端API(写SQL,从事于大数据开发,SQL是基础核心)

4.Phoenix结构(Hbase)

在这里插入图片描述

1.Phoenix分为胖客户端和瘦客户端
2.胖客户端对SQL解析=>Hbase读写原理API=>直接作用于zookeeper
3.瘦客户端通过Phoenix Query Server 来解析SQL语言。

5.Phoenix安装

安装教程

6.Phoenix Shell

在使用之前开启hadoop集群和zookeeper一级hbase集群

进入phoenix/bin目录去查看
在这里插入图片描述
sqlline.py代表胖客户端,sqlline-thin.py代表瘦客户端

6.1使用胖客户端进行连接

[atguigu@hadoop102 phoenix]$ sqlline.py hadoop102,hadoop103,hadoop104:2181

这里使用三个ip,其实我们使用一个IP连也行,只不过连三个IP为了防止某个节点挂掉。

在这里插入图片描述
常用命令操作

6.2使用瘦客户端进行连接

1.直接连,不启动queryserver.py

[atguigu@hadoop102 phoenix]$ sqlline-thin.py http://hadoop102:8765

在这里插入图片描述

2.先启动queryserver.py连接,不然连接报错

-rwxr-xr-x. 1 atguigu atguigu  7761 6月  27 2018 queryserver.py
queryserver.py

在这里插入图片描述
阻塞式进程,在开启一个102再次连接
在这里插入图片描述
就可以操作shell命令了。

6.3常用命令

说明:
1.在phoenix处理的命令都是处理Hbase里面的数据,需要在开启一个窗口,进入hbase shell界面来查询在phoenix操作后hbase里面的数据变化。
2.phoenix底层都在Hbase那边
在这里插入图片描述
在这里插入图片描述

(1)查询所有表信息

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> !tables

在这里插入图片描述
(2)创建表(一般在企业中都已经提供,很少需要自己写,一般都是使用脚本进行导入)

CREATE TABLE IF NOT EXISTS student33(
id VARCHAR primary key,
name VARCHAR,
addr VARCHAR);

在这里插入图片描述
说明:
1.Hbase中使用phoenix创建表,表一定要指定主键。在Hbase中没有主键即rowkey是没有办法运行的。
2.在phoenix中,表名等会自动转换为大写,若要小写,使用双引号,如"us_population"。

(3)插入数据

upsert into STUDENT33 values('1001','zhangsan','beijing');

说明:为什么是upsert?在Hbase底层修改和追加是一样的命令。

(4)查询

select * from STUDENT33;

在这里插入图片描述
颜色高亮显示,代表索引。
说明:
在hbase shell中扫描一下刚才创建的表STUDENT33

hbase(main):002:0> scan 'STUDENT33'
ROW                                              COLUMN+CELL                                                                                                                                 
 1001                                            column=0:\x00\x00\x00\x00, timestamp=1615028451315, value=x                                                                                 
 1001                                            column=0:\x80\x0B, timestamp=1615028451315, value=zhangsan                                                                                  
 1001                                            column=0:\x80\x0C, timestamp=1615028451315, value=beijing                                                                                   
1 row(s)
Took 0.1190 seconds                                                                                                                                                                          
hbase(main):003:0> 

结果说明:
1.rowkey是一样
2.x代表神秘 可以指是你插入数据只有rowkey
在这里插入图片描述
在phoenix在创建一张student33表,不插入数据
在这里插入图片描述
说明:column=0:\x00\x00\x00\x00, timestamp=1615028451315, value=x 这条数据随着upsert进来的
那么这条数据到底是什么呢?
我们往STUDENT33这个表插入一条只有rowkey,其他为空的信息

upsert into student33 values('1002',null,null);

在这里插入图片描述
在这里插入图片描述
若不想对列名编码,可在建表语句末尾加上COLUMN_ENCODED_BYTES = 0;
官网资料
在这里插入图片描述

3.例如 column=0:\x00\x00\x00\x00代表列名经过序列化了,改掉了之后存在Hbase里面
(5)删除记录

delete from student where id='1001';

(6)删除表

drop table student;

(7)退出命令行

!quit

(8)创建视图

Phoenix创建的视图是只读的,所以只能用来做查询,无法通过视图对源数据进行修改等操作。在phoenix中创建关联test表的视图
0: jdbc:phoenix:hadoop101,hadoop102,hadoop103> create view "test"(id varchar primary key,"info1"."name" varchar, "info2"."address" varchar);
删除视图
0: jdbc:phoenix:hadoop101,hadoop102,hadoop103> drop view "test";

(9)创建表格

在Pheonix创建表去映射HBase中已经存在的表,是可以修改删除HBase中已经存在的数据的。而且,删除Phoenix中的表,那么HBase中被映射的表也会被删除。
注:进行表映射时,不能使用列名编码,需将column_encoded_bytes设为0。
0: jdbc:phoenix:hadoop101,hadoop102,hadoop103> create table "test"(id varchar primary key,"info1"."name" varchar, "info2"."address" varchar) column_encoded_bytes=0;

6.4phoenixJDBC操作

主要是在IDEA中怎么创建胖客户端和瘦客户端。
我的博客

6.5 Phoenix二级索引

配置phoenix文件需要分发到对应的节点上去
二级索引主要分为:全局索引,包含索引,本地索引。
全局索引:适用于多读少写场景。(创建索引目的就是为了读,写容易造成写重复的问题。本来只需要写一张表写一次就可以,但因为你创建了二级索引,你在写原表的时候,同时也要写索引的表如果你建的索引越多,需要写的次数就越多,所以会造成重复写,同时对写的性能有所下降)
有一个问题,对读的性能提升,但对磁盘的消耗增大,这个我们还可以接受,对于大数据而言,磁盘是最不值钱的。这也是phoenix建立二级索引最核心的点,这样的话你读这个表rowkey设计的时候压力没那么大

实际操作

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select * from student;

在这里插入图片描述
如何识别你是全表扫描的还是范围扫描的?
explain

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select * from student;
+-------------------------------------------------------------------+-----------------+----------------+--------------+
|                               PLAN                                | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER STUDENT  | null            | null           | null         |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
1 row selected (0.153 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> 

SCAN OVER STUDENT 可以看出是全表扫描。
切记,在公司千万别使用select 查询所有信息,那样很容易崩掉,尤其是大数据开发。

想要查看不是全表扫描是范围扫描,我们可以以下面方式实现
方法一:

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select name from student where id = '1001';
+-----------+
|   NAME    |
+-----------+
| zhangsan  |
+-----------+
1 row selected (0.093 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select name from student where id = '1001';
+------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
|                                              PLAN                                              | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK 1 ROWS 205 BYTES PARALLEL 1-WAY ROUND ROBIN POINT LOOKUP ON 1 KEY OVER STUDENT  | 205             | 1              | 0            |
+------------------------------------------------------------------------------------------------+-----------------+----------------+--------------+
1 row selected (1.294 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> 

说明:如果我们使用名字进行查询就会变成全表扫描,并不是语句不能查,没有用到索引

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select addr from student where name = 'linhai';
+-------------------------------------------------------------------+-----------------+----------------+--------------+
|                               PLAN                                | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER STUDENT  | null            | null           | null         |
|     SERVER FILTER BY NAME = 'linhai'                              | null            | null           | null         |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
2 rows selected (1.214 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> 

SCAN OVER 是全表扫描。进行测试的时候显示比较快,是你的数据量太少。因此根据这种情况,我们需要去建立二级索引,根据姓名查询地址。

建立二级索引公式
CREATE INDEX 索引表名字 ON 要操作的表 (想要建立索引对应的名字);

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> CREATE INDEX my_name ON student (name);
1 row affected (11.441 seconds)

建立索引比较慢,因此我们在实际开发过程中,需要在表设计好后,就建立二级索引。这样开发提升项目效率。
在这里插入图片描述
我们还以到hbase shell 界面去查询下这个表的信息,进行对比。
在这里插入图片描述
保存数据的格式和我们预期的一样,名字中间连接符对应ID,这里连接符号使用序列化后的\x00
把列名和主键拼接到了一起。

接下来测试 能否生效

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select addr from student where name = 'linhai';
+-------------------------------------------------------------------+-----------------+----------------+--------------+
|                               PLAN                                | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER STUDENT  | null            | null           | null         |
|     SERVER FILTER BY NAME = 'linhai'                              | null            | null           | null         |
+-------------------------------------------------------------------+-----------------+----------------+--------------+
2 rows selected (0.211 seconds)

结果还是全表扫描。但我们用到了二级索引,先用二级索引,没有扫描到linhai对应字段addr信息,然后在全表扫描,所以结果是这样。

比如,如果你知道名字使用范围扫描,在试下。

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select id from student where name = 'linhai';
+-------------------------------------------------------------------------------+-----------------+----------------+--------------+
|                                     PLAN                                      | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+-------------------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER MY_NAME ['linhai']  | null            | null           | null         |
|     SERVER FILTER BY FIRST KEY ONLY                                           | null            | null           | null         |
+-------------------------------------------------------------------------------+-----------------+----------------+--------------+
2 rows selected (0.088 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select id from student where name = 'zhangsan';
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
|                                      PLAN                                       | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER MY_NAME ['zhangsan']  | null            | null           | null         |
|     SERVER FILTER BY FIRST KEY ONLY                                             | null            | null           | null         |
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
2 rows selected (0.622 seconds)

因此这样使用的就是范围扫描。RANGE SCAN
也就是你建立的索引,如果只包含ID的话,你在查询的当中,前面有不包含的列,就没有办法用到这个索引,等于这个索引白建立了,这是全局索引的一个缺陷。

好用的方法你就是把addr也加入进来。即包含索引。

包含索引:包含索引的本质和全局索引的本质是一样。都是新创建一个表,表里面是你需要建立索引的东西和例如200个主键拼接到一起。后面你可以添加一些列的信息。
比如说我们这里可以添加ADDR的信息。
演示:
删除原先建立的索引。

2 rows selected (0.622 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> drop index my_name on student;
No rows affected (4.697 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104>

重新建立包含索引。

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> create index my_name on student(name) include(addr);
1 row affected (8.185 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select * from my_name;
+-----------+-------+----------+
|  0:NAME   |  :ID  |  0:ADDR  |
+-----------+-------+----------+
| zhangsan  | 1001  | beijing  |
+-----------+-------+----------+
1 row selected (2.554 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select addr from student where name ='zhangsan';
+----------+
|   ADDR   |
+----------+
| beijing  |
+----------+
1 row selected (0.502 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> explain select addr from student where name ='zhangsan';
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
|                                      PLAN                                       | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER MY_NAME ['zhangsan']  | null            | null           | null         |
+---------------------------------------------------------------------------------+-----------------+----------------+--------------+
1 row selected (0.527 seconds)

可以看到现在就是使用了那个索引,是范围扫描。在hbase shell再去扫描一下,进行对比。
在这里插入图片描述
对比发现,比刚才多加了一条消息。
zhangsan\x001001 column=0:\x80\x0B, timestamp=1615200483399, value=beijing

这就是包含索引。

在实际生产中,包含索引用到比较多,这样可以减少rowkey设计考虑的问题。
把你想要的信息放在二级索引里面,添加上你想要查询对应的属性字段,因此我们使用phoenix主要就是使用这个功能。

**本地索引:**就是即想创建一个二级索引,又不想额外写一张表,包含索引容易造成一个问题,读的时候,出现多个节点进行跳转。本地索引可以实现这个操作。
注意这个本地是你的表在哪,不是你的计算机IP,本地索引还能智能判断你的Range的范围。
演示:

0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> drop index my_name on student;
No rows affected (2.32 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> create local index my_name on student(name);
1 row affected (24.909 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select * from my_name;
+-----------+-------+
|  0:NAME   |  :ID  |
+-----------+-------+
| zhangsan  | 1001  |
+-----------+-------+
1 row selected (0.197 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104> select * from student;
+-------+-----------+----------+
|  ID   |   NAME    |   ADDR   |
+-------+-----------+----------+
| 1001  | zhangsan  | beijing  |
+-------+-----------+----------+
1 row selected (0.114 seconds)
0: jdbc:phoenix:hadoop102,hadoop103,hadoop104>

在hbase shell中我们扫描创建的索引表,发现没有,本地索引,hbase底层没有这个表,本地索引模式不额外创建一个表,扫描STUDENT这个表发现有你创建二级索引的信息。

hbase(main):007:0> list
TABLE                                                                                                                                                                                        
STUDENT                                                                                                                                                                                      
STUDENT33                                                                                                                                                                                    
SYSTEM.CATALOG                                                                                                                                                                               
SYSTEM.FUNCTION                                                                                                                                                                              
SYSTEM.LOG                                                                                                                                                                                   
SYSTEM.MUTEX                                                                                                                                                                                 
SYSTEM.SEQUENCE                                                                                                                                                                              
SYSTEM.STATS                                                                                                                                                                                 
US_POPULATION                                                                                                                                                                                
bigdata:order                                                                                                                                                                                
shuff4                                                                                                                                                                                       
staff1                                                                                                                                                                                       
staff2                                                                                                                                                                                       
staff3                                                                                                                                                                                       
student                                                                                                                                                                                      
student33                                                                                                                                                                                    
student88                                                                                                                                                                                    
test                                                                                                                                                                                         
test_number                                                                                                                                                                                  
19 row(s)
Took 0.0108 seconds                                                                                                                                                                          
=> ["STUDENT", "STUDENT33", "SYSTEM.CATALOG", "SYSTEM.FUNCTION", "SYSTEM.LOG", "SYSTEM.MUTEX", "SYSTEM.SEQUENCE", "SYSTEM.STATS", "US_POPULATION", "bigdata:order", "shuff4", "staff1", "staff2", "staff3", "student", "student33", "student88", "test", "test_number"]
hbase(main):008:0> scan "STUDENT"
ROW                                              COLUMN+CELL                                                                                                                                 
 \x00\x00zhangsan\x001001                        column=L#0:\x00\x00\x00\x00, timestamp=1614996361813, value=\x00\x00\x00\x00                                                                
 1001                                            column=0:\x00\x00\x00\x00, timestamp=1614996361813, value=x                                                                                 
 1001                                            column=0:\x80\x0B, timestamp=1614996361813, value=zhangsan                                                                                  
 1001                                            column=0:\x80\x0C, timestamp=1614996361813, value=beijing                                                                                   
2 row(s)
Took 0.0417 seconds

rowkey为这个\x00\x00zhangsan\x001001 就是本地索引存储对应的信息。
总结:本地索引对写的性能更加好一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值