day 50 HBase phoenix 安装 二级索引

文章目录


I know, i know
地球另一端有你陪我




一、phoenix


Hbase适合存储大量的对关系运算要求低的NOSQL数据,受Hbase 设计上的限制不能直接使用原生的API执行在关系数据库中普遍使用的条件判断和聚合等操作。Hbase很优秀,一些团队寻求在Hbase之上提供一种更面向普通开发人员的操作方式,Apache Phoenix即是。

Phoenix 基于Hbase给面向业务的开发人员提供了以标准SQL的方式对Hbase进行查询操作,并支持标准SQL中大部分特性:条件运算,分组,分页,等高级查询语法。
1 关闭 hbase 集群

1、安装

stop-hbase.sh

2 解压再改名

tar -xvf apache-phoenix-4.15.0-HBase-1.4-bin.tar.gz -C ...

3 改名

mv apache-phoenix-4.15.0-HBase-1.4-bin phoenix-4.15.0

4 将所有节点 hbase 下的文件进行替换

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar master:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node1:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node2:/usr/local/soft/hbase-1.4.6/lib/

5 配置环境变量

vim /etc/profile

/usr/local/soft/phoenix-4.15.0/bin

source /etc/profile

6 打开 hbase

start-hbase.sh

7 连接 sqlline

sqlline.py master,node1,node2

2、常用指令

phoenix 中表明严格区分大小写,使用小写作为表名时,使用时必须加上双引号 " "
hbase 中,所有的表名都使用时都需要加上单引号 ’ ’

1 建表
   没太多区别,表名小写的话记得双引号

create table if not exists "pokemon" (
id varchar not null primary key, 
name varchar,
level varchar
);

2 显示所有表
   不需要引号

!table

3 插入数据
   update + insert = upsert

upsert into "pokemon" values('01','piplup','5');
upsert into "pokemon" values('02','ralts','8');

4 查询 删除
   都差不多

select * from "pokemon" where name='piplup';

delete from "pokemon" where id='01';

drop table STUDENT;

5 退出 phoenix

!quit

3、视图映射

默认情况下,直接在 hbase 中创建的表,通过 phoenix 是查看不到的
如果需在 phoenix 中操作在 hbase 中创建的表,则需要在 phoenix 中进行表的映射。
映射方式有两种:视图映射和表映射

3.1、视图映射

1) 当HBase中已经存在表时,可以以类似创建视图的方式创建关联表,
只需要将create table 改为create view 即可

# hbase shell 进入hbase命令行
hbase shell 

# 创建hbase表
create 'test','name','company' 

# 插入数据
put 'test','001','name:firstname','zhangsan1'
put 'test','001','name:lastname','zhangsan2'
put 'test','001','company:name','数加'
put 'test','001','company:address','合肥'


# 在phoenix创建视图, primary key 对应到hbase中的rowkey

create view "test"(
empid varchar primary key,
"name"."firstname" varchar,
"name"."lastname"  varchar,
"company"."name"  varchar,
"company"."address" varchar
);

CREATE view "student" (
 id VARCHAR NOT NULL PRIMARY KEY, 
 "info"."name" VARCHAR,
 "info"."age" VARCHAR, 
 "info"."gender" VARCHAR ,
 "info"."clazz" VARCHAR
) column_encoded_bytes=0;

# 在phoenix查询数据,表名通过双引号引起来
select * from "test";

# 删除视图
drop view "test";

Phoenix创建的视图是只读的,只能用来做查询,无法通过视图对源数据进行修改等操作

3.2、表映射

2)当HBase中不存在表时,可以直接使用 create table 指令创建需要的表,
并且在创建指令中可以根据需要对 HBase 表结构进行显示的说明

create table "test" (
empid varchar primary key,
"name"."firstname" varchar,
"name"."lastname"varchar,
"company"."name"  varchar,
"company"."address" varchar
)column_encoded_bytes=0;

upsert into  "test"  values('1','2','3','4','5');

CREATE table  "student" (
 id VARCHAR NOT NULL PRIMARY KEY, 
 "info"."name" VARCHAR,
 "info"."age" VARCHAR, 
 "info"."gender" VARCHAR ,
 "info"."clazz" VARCHAR
) column_encoded_bytes=0;

upsert into "student" values('15004','葛德曜','24','女','理科三班');

使用create table创建的关联表,如果对表进行了修改,
源数据也会改变,同时如果关联表被删除,源表也会被删除;
但是视图就不会,如果删除视图,源数据不会发生改变。


二、二级索引

hbase 本身不支持索引,但由于三重有序,能够使用二分查找,加上布隆过滤器
能够较快的找到 rowkey 的位置

倘若不通过rowkey查找数据,就必须逐行比较每一行的值,
对于较大的表,全表扫描的代价是不可接受的

此时就引入了二级索引(建立行键与列值的映射关系)
day 50 HBase phoenix 安装 二级索引

1、开启索引支持

1 关闭hbase集群

stop-hbase.sh

2 开启索引支持,增加如下配置信息

cd /usr/local/soft/hbase-1.4.6/conf/

vim hbase-site.xml
    <property>
      <name>hbase.regionserver.wal.codec</name>
      <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
    </property>
    <property>
        <name>hbase.rpc.timeout</name>
        <value>60000000</value>
    </property>
    <property>
        <name>hbase.client.scanner.timeout.period</name>
        <value>60000000</value>
    </property>
    <property>
        <name>phoenix.query.timeoutMs</name>
        <value>60000000</value>
    </property>

3 同步到所有节点

scp hbase-site.xml node1:`pwd`
scp hbase-site.xml node2:`pwd`

4 启动 hbase,重新进入 phoenix

start-hbase.sh

sqlline.sql master,node1,node2

2、全局索引

全局索引适合读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)

注意: 对于全局索引在默认情况下,在查询语句中检索的列如果不在索引表中,
Phoenix不会使用索引表将,除非使用 hint

# 创建新文件 DIANXIN.sql
CREATE TABLE IF NOT EXISTS DIANXIN (
     mdn VARCHAR ,
     start_date VARCHAR ,
     end_date VARCHAR ,
     county VARCHAR,
     x DOUBLE ,
     y  DOUBLE,
     bsid VARCHAR,
     grid_id  VARCHAR,
     biz_type VARCHAR, 
     event_type VARCHAR , 
     data_source VARCHAR ,
     CONSTRAINT PK PRIMARY KEY (mdn,start_date)
) column_encoded_bytes=0;

# 上传数据 DIANXIN.csv

# 导入数据
psql.py master,node1,node2 DIANXIN.sql DIANXIN.csv

# 创建全局索引
CREATE INDEX DIANXIN_INDEX ON DIANXIN ( end_date );

# 查询数据 ( 索引未生效)
select * from DIANXIN where end_date = '20180503154014';

# 强制使用索引 (索引生效) hint
select /*+ INDEX(DIANXIN DIANXIN_INDEX) */  *
from DIANXIN where end_date = '20180503154014';

select /*+ INDEX(DIANXIN DIANXIN_INDEX) */  *
from DIANXIN where end_date = '20180503154014'
and start_date = '20180503154614';

# 取索引列,(索引生效)
select end_date from DIANXIN where end_date = '20180503154014';

此处是先将原数据的两个列(mdn,start_date)拼接,作为 primary key
再创建二级索引,将 end_date 作为第二级的索引
此时二级索引的键值格式为(end_date,mdn,start_date)

这样再次通过二级索引进行查询时,会进行 rowkey 前缀查询
因此使用二级索引搜索,会大大加快查询速度

注1:由于是前缀查询,若是直接通过主键后面的值查询
(如此处的mdn,start_date),速度会和没有索引时一样

注2:若是只取键值中的字段,通过索引查找,会自动使用二级索引

# 创建多列索引
CREATE INDEX DIANXIN_INDEX1 ON DIANXIN ( end_date,COUNTY );

# 多条件查询 (索引生效)
select end_date,MDN,COUNTY from DIANXIN 
where end_date = '20180503154014' and COUNTY = '8340104';

# 查询所有列 (索引未生效)
select  * from DIANXIN 
where end_date = '20180503154014'  and COUNTY = '8340104';

# 查询所有列 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX1) */ * from DIANXIN 
where end_date = '20180503154014' and COUNTY = '8340104';

# 单条件  (索引未生效)
select end_date from DIANXIN where  COUNTY = '8340103';
# 单条件  (索引生效) end_date 在前
select COUNTY from DIANXIN where end_date = '20180503154014';

# 删除索引
drop index DIANXIN_INDEX on DIANXIN;

3、本地索引

本地索引适合写多读少的场景,或者存储空间有限的场景。
和全局索引一样,Phoenix 也会在查询的时候自动选择是否使用本地索引,
本地索引因为索引数据和原数据存储在同一台机器上,避免网络数据传输的开销,所以更适合写多的场景。
由于无法提前确定数据在哪个Region上,所以在读数据的时候,需要检查每个Region上的数据从而带来一些性能损耗。

注意:对于本地索引,查询中无论是否指定hint或者是查询的列是否都在索引表中,都会使用索引表。

# 创建本地索引
CREATE LOCAL INDEX DIANXIN_LOCAL_IDEX ON DIANXIN(grid_id);

# 索引生效
select grid_id from dianxin where grid_id='117285031820040';

# 索引生效
select * from dianxin where grid_id='117285031820040';

进过测试,本地索引是在原表的基础上,再开一个列簇,将合并出来的 rowkey 放在新的列簇里,由于都是在原表上进行,所以不会被检测出新的表


4、覆盖索引

覆盖索引是把原数据存储在索引数据表中,这样在查询时不需要再去HBase的原表获取数据就,直接返回查询结果。

注意:查询是 select 的列和 where 的列都需要在索引中出现。

# 创建覆盖索引
CREATE INDEX DIANXIN_INDEX_COVER ON DIANXIN (x,y) INCLUDE (county);

# 查询所有列 (索引未生效)
select * from DIANXIN where x=117.288 and y =31.822;

# 强制使用索引 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ * 
from DIANXIN where x=117.288 and y =31.822;

# 查询索引中的列 (索引生效) mdn是DIANXIN表的RowKey中的一部分
select x,y,county from DIANXIN where x=117.288 and y =31.822;
select mdn,x,y,county from DIANXIN where x=117.288 and y =31.822;

# 查询条件必须放在索引中  select 中的列可以放在INCLUDE (将数据保存在索引中)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ x,y,count(*) 
from DIANXIN group by x,y;

三、Phoenix JDBC

先导依赖

<dependency>
    <groupId>org.apache.phoenix</groupId>
    <artifactId>phoenix-core</artifactId>
    <version>4.15.0-HBase-1.4</version>
</dependency>
Connection conn = DriverManager
.getConnection("jdbc:phoenix:master,node1,node2:2181");

        PreparedStatement ps = conn
        .prepareStatement("select /*+ INDEX(DIANXIN DIANXIN_INDEX) */ * from DIANXIN where end_date=?");
        
        ps.setString(1, "20180503212649");
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            String mdn = rs.getString("mdn");
            String start_date = rs.getString("start_date");
            String end_date = rs.getString("end_date");
            String x = rs.getString("x");
            String y = rs.getString("y");
            String county = rs.getString("county");
            System.out.println(mdn + "\t" + start_date 
            + "\t" + end_date + "\t" + x + "\t" + y + "\t" + county);
        }
        ps.close();
        conn.close();

总结

1、单独开启 hbase 的节点,在 hbase 的 bin 目录下

daemon.sh start master
daemon.sh start regionserver

如果没添加路径就

./daemon.sh start master

2、在 phoenix 中创建 hbase 中已存在的表,会在原表的基础上添加新的列簇

上一篇:HBase - Phoenix的安装使用教程1(基本介绍、安装部署)


下一篇:hbase调优