phonex的使用,二级索引,预分区,调优

  • Hbase适合存储大量的对关系运算要求低的NOSQL数据,受Hbase 设计上的限制不能直接使用原生的PAI执行在关系数据库中普遍使用的条件判断和聚合等操作。
  • Apache Phoenix提供一种更面向普通开发人员的操作方式
  • Phoenix 基于Hbase给面向业务的开发人员提供了以标准SQL的方式对Hbase进行查询操作,并支持标准SQL中大部分特性:条件运算,分组,分页,等高级查询语法。

一、基本指令

使用phonex
sqlline.py master,node1,node2

  • 用了phonex就只能存储结构化的数据,不能存储半结构化和非结构化的数据

1)创建表

建表的时候必须要指定主键,或者会报错

CREATE TABLE IF NOT EXISTS STUDENT1 (
 id VARCHAR NOT NULL PRIMARY KEY, 
 name VARCHAR,
 age BIGINT, 
 gender VARCHAR ,
 clazz VARCHAR
);

在HBASE中查看表的结构
在phonex中创建的表比在hbase中的表多了一段代码,这部分叫做协处理器,就是在region中运行的一段代码,用于自动处理索引
在这里插入图片描述

2)删除表

在这里插入图片描述
删除所有在phonex中创建的表,观察HBASE中是否还有
在这里插入图片描述
发现hbase中也没有了

3)插入数据

在这里插入图片描述

4)查询数据

查询全部

在这里插入图片描述
虽然也可以分组,汇总,但是不适合该操作,当数据多的时候,数据非常慢,计算量也很大,可能会导致hbase集群崩溃
在这里插入图片描述

5)删除数据

支持where操作,速度快
在这里插入图片描述

6)退出命令行

!quit

二、映射

  • 默认情况下,直接在hbase中创建的表,通过phoenix是查看不到的
  • 如果需要在phoenix中操作直接在hbase中创建的表,则需要在phoenix中进行表的映射
  • 映射方式有两种:视图映射和表映射。(视图映射,表映射)ou
  • 为表创建映射时,需保证,表是结构化的,不能为非结构化和半结构化的表创建映射

1)视图映射

  • Phoenix创建的视图是只读的,所以只能用来做查询

在hbase中找一个student表,在phonex中为该表创建视图映射,由于原表中已经有了一个STUDENT,在phonex中会自动将表名转为大写,便于区分,这里加上引号创建student映射,但是注意,查询的时候也需要加上引号

首先在HBASE中查看student的列族和列的名字,了解表的结构
在这里插入图片描述

创建视图

在phonex中创建视图映射,和创建表一样必须指定主键,这里的主键就是HBASE表中的rowkey,字段名可以任意起,这里为id

create view "student" (
id varchar primary key,
"info"."age" varchar,
"info"."clazz"varchar,
"info"."name"  varchar,
"info"."sex" varchar
);

在这里插入图片描述

查询视图

在这里插入图片描述

删除视图

drop view “student”;
在这里插入图片描述
HBASE中依然存在,因为视图是只读的
在这里插入图片描述

2)表映射

  • 创建映射表的时候,Phoenix会在表中创建一些空的键值对,会生成原表对应字段的映射,故创建表时,需加上column_encoded_bytes=0,否者用原表的字段名在去查询时,对应的映射中查询,会查询不到
  • 使用Apache Phoenix创建对HBase的表映射,有两种方法:
    • 1) 当HBase中已经存在表时,可以以类似创建视图的方式创建关联表,只需要将create view改为create table即可。
    • 2)当HBase中不存在表时,可以直接使用create table指令创建需要的表,并且在创建指令中可以根据需要对HBase表结构进行显示的说明。

方法1

create table "student" (
empid varchar primary key,
"info"."age" varchar,
"info"."clazz"varchar,
"info"."sex"  varchar,
"info"."name" varchar
) column_encoded_bytes=0;

在这里插入图片描述
方法2
这样系统将会自动在Phoenix和HBase中创建表,并会根据指令内的参数对表结构进行初始化。
使用create table创建的关联表,如果对表进行了修改,源数据也会改变,同时如果关联表被删除,源表也会被删除。但是视图就不会,如果删除视图,源数据不会发生改变。

创建一个HBASE中不存在的表的映射

create table "stu" (
empid varchar primary key,
"info"."age" varchar,
"info"."clazz"varchar,
"info"."sex"  varchar,
"info"."name" varchar
) column_encoded_bytes=0;

在这里插入图片描述
hbase中也有该表的信息
在这里插入图片描述

删除表

在这里插入图片描述
hbase中也被删除,如果被更改,hbase中也被更改在这里插入图片描述

3)视图映射和表映射的区别

  • 相比于直接创建映射表,视图的查询效率会低,原因是:创建映射表的时候,Phoenix会在表中创建一些空的键值对,这些空键值对的存在可以用来提高查询效率。
  • 视图映射是只读的操作,不会对原表进行修改,表映射和原表关联,对表映射的更改,也会影响hbase中的表

三、二级索引

  • 对于Hbase,如果想精确定位到某行记录,唯一的办法就是通过rowkey查询。如果不通过rowkey查找数据,就必须逐行比较每一行的值,对于较大的表,全表扫描的代价是不可接受的。
  • 索引分为全局索引和本地索引

1)修改配置文件

关闭hbase的集群,修改配置文件
修改配置文件,设置RPC请求的超时时间。默认为60s,由于电脑性能和数据量,需要修改的长一点,RPC时间超过该值,客户端就会主动关闭socket

关闭集群
在这里插入图片描述
修改phonex下的hbase-site.xml

<property>
<name>phoenix.query.timeoutMs</name>
<value>500000</value>
</property>

在这里插入图片描述

在这里插入图片描述

修改hbase下的hbase-site.xml
如果不是伪分布式,还需将该文件分别发送到子节点的对应目录下
在这里插入图片描述

<property>
  <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
    </property>
<property>
<name>phoenix.query.timeoutMs</name>
<value>500000</value>
</property> 

在这里插入图片描述

两个文件修改完后,启动集群
在这里插入图片描述

2)全局索引

  • 全局索引适合读多写少的场景。
  • 如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。
  • 数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)、
  • 注意: 对于全局索引在默认情况下,在查询语句中检索的列如果不在索引表中,Phoenix不会使用索引表将,除非使用hint。
  • hint是一种添加注解的方式

这里个建一个数据量比较大的表,效果明显
创建表,由于手机号并非每条数据的唯一标识,需要用,联合主键,由于建表,再向表插数据,速度慢,将建表语句放入一个sql文件中,使用指令导入数据到表中

创建sql文件
在这里插入图片描述
上传数据
在这里插入图片描述
执行指令,导入数据
在这里插入图片描述

进入phonex

在这里插入图片描述
这是一个普通的表,查询测试时间

根据mdn查询数据
在这里插入图片描述
根据start_data查询数据
在这里插入图片描述

根据end_data查询数据
在这里插入图片描述

以上的测试也应证了,前缀比较器比其他子串比较器要快行过滤器比列值过滤器速度快
前缀加行过滤器最快

增加索引

根据需求,为要查找的字段增加全局索引,此处以end_data为例
在这里插入图片描述
这里会多了一个索引表,hbase中也是
在这里插入图片描述
在这里插入图片描述
查询数据,会发现没很大区别,这是因为索引没生效,查找的数据含有非索引字段的部分
在这里插入图片描述
只查询索引字段,时间明显减少,可见索引生效
在这里插入图片描述
要想查询非索引字段的时候,让索引生效,可以使用加上hint的方法

加上 /*+ INDEX(DIANXIN DIANXIN_INDEX) */ 强制使用索引

在这里插入图片描述
在这里插入图片描述

删除索引

drop index DIANXIN_INDEX on dianxin;
在这里插入图片描述

创建多列索引

CREATE INDEX DIANXIN_INDEX1 ON DIANXIN (end_date,start_date);
在这里插入图片描述
查询索引列,索引生效
在这里插入图片描述
此处只能where后面只能筛选这个end_date的或者end_date和start_date才会生效,用start_date不生效
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查询含非索引的列和非key值的列
在这里插入图片描述
使索引生效
在这里插入图片描述

3)本地索引

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

创建索引

在这里插入图片描述
在这里插入图片in描述
但在HBASE中只有一个索引表,本地索引和数据表在一个表里
在这里插入图片描述

观察全局索引和本地索引的表的不同

本地索引=》数据表
在这里插入图片描述
全局索引
在这里插入图片描述
测试
查询索引字段
select grid_id from dianxin where grid_id='117285031820040’
索引生效
在这里插入图片描述
查询非索引的字段
select * from dianxin where grid_id='117285031820040’
索引生效
在这里插入图片描述

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;

在这里插入图片描述
查询索引中的列,索引生效
select x,y,county from dianxin where x=117.288 and y =31.822;

在这里插入图片描述
查询条件必须放在索引中,查询字段作为覆盖

四、java代码使用phonex

在java项目中,加入phonex对应版本的依赖
注意此处必须加入与HBASE版本对应的依赖

        <dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-core</artifactId>
            <version>4.15.0-HBase-1.4</version>
        </dependency>

在这里插入图片描述

代码演示

import java.sql.*;

public class Dianxin_Demo {
    public static void main(String[] args) throws SQLException {

        //建立连接,连接zookeeper
        Connection conn = DriverManager.getConnection("jdbc:phoenix:master:2181");
        //建立预处理的sql
        PreparedStatement ps = conn.prepareStatement("select * from DIANXIN where mdn=?");
        //设置参数的值
        ps.setString(1,"47BE1E866CFC071DB19D5E1C056BE28AE24C16E7");
        //执行查询操作,获取结果集
        ResultSet resultSet = ps.executeQuery();
        while ((resultSet.next())){
            String mdn = resultSet.getString("mdn");
            String start_date = resultSet.getString("start_date");
            String end_date = resultSet.getString("end_date");
            String county = resultSet.getString("county");
            String x = resultSet.getString("x");
            String y = resultSet.getString("y");
            System.out.println(mdn+"\t"+start_date+"\t"+end_date+"\t"+county+"\t"+x+"\t"+y);
        }
        conn.close();

    }
}

上面有许多警告信息,但是不影响结果
在这里插入图片描述

五、phonex调优

配置超时

增加超时时间,phnoex,master和子节点 都要添加

 <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>

预分区

方法一

在创建表的时候,根据指定主键要分区的值

CREATE TABLE IF NOT EXISTS STUDENT (
 id VARCHAR NOT NULL PRIMARY KEY, 
 name VARCHAR,
 age BIGINT, 
 gender VARCHAR ,
 clazz VARCHAR
)split on('1500100615','1500100721','1500100742') ;

方法二

加盐:在创建表的时候指定salting。
在rowkey前面加上一个随机的前缀

CREATE TABLE IF NOT EXISTS STUDENT (
 id VARCHAR NOT NULL PRIMARY KEY, 
 name VARCHAR,
 age BIGINT, 
 gender VARCHAR ,
 clazz VARCHAR
)salt_buckets=4;

优点:不需要知道rowkey的分步情况
缺点:不能在hbase中根据rowkey对数据进行查询和修改

rowkey的设计

  • rowkey按字典升序排列,如果想要倒叙排列,可以采用大数减小数的方法
  • rowkey尽量不要太长,因为每个列中也存有rowkey的信息,rowkey太长,会导致数据量很大
  • rowkey的设计原则
    • 长度原则
    • 散列原则
    • 唯一原则

in memory

  • 创建表的时候,可以通过HColumnDescriptor.setInMemory(true)将表放到 RegionServer的缓存中,保证在读取的时候被cache命中。

version

  • 创建表的时候,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)设置 表中数据的最大版本,如果只需要保存最新版本的数据,那么可以设置 setMaxVersions(1)。

java
java入门基础学习(一)
java入门基础学习(二)
java入门基础学习(三)
java入门基础学习(四)
java入门基础学习(五)
java入门基础学习(六)
java入门基础学习(七)
java入门基础学习(八)
java入门基础学习(九)
java入门基础学习(十)
java入门基础学习(十一)
java入门基础学习(十二)
java入门基础学习(十三)
java入门基础学习(十四)Maven Git
java总结,题目+笔记
java进阶之常见对象(一)
java进阶之常见对象(二)
java进阶之冒泡排序
java进阶之选择排序
java进阶之面向对象(封装)
java进阶之面向对象(代码块、继承)
java进阶之面向对象(多态、抽象、接口)
java进阶之匿名内部类、访问修饰符、包
java进阶之io流(字节流,字符流)
java应用一(反射的应用)
java应用二(配置文件、工具类)
java应用三(数据库索引、spring)
java应用四(连接池)
Linux
Linux基础一
Linux基础二
Linux基础三
Linux基础四
Linux基础五
Mysql
mysql一
mysql二
mysql三
mysql四
java连接数据库
redis
redis一(缓存,redis简介)
redis二(单节点安装,桌面插件)
redis三(指令的使用)
redis四(java与redis的连接,基本指令在java中的操作)
redis五(练习)
redis七(持久化)
redis九(集群安装)
Hadoop
hadoop学习一
hadoop学习二
hadoop学习三
hadoop学习四
hadoop学习五
hadoop学习六
hadoop学习七
hadoop学习八
hadoop异常处理
hadoop基础学习九
hadoop基础学习十
hadoop基础学习十一
hadoop基础学习十二
hadoop基础学习十三
hadoop基础学习十四
hadoop基础学习十五
hadoop基础学习十六
hadoop基础学习十七
hadoop基础学习十八

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值