Phoenix

Phoenix的介绍

  • 功能

    • 专门基于Hbase所设计的SQL on Hbase 工具

    • 使用Phoenix实现基于SQL操作Hbase

    • 使用Phoenix自动构建二级索引并维护二级索引

  • 原理

    • 上层提供了SQL接口

      • 底层全部通过Hbase Java API来实现,通过构建一系列的Scan和Put来实现数据的读写
    • 功能非常丰富

      • 底层封装了大量的内置的协处理器,可以实现各种复杂的处理需求,例如二级索引等
  • 特点

    • 优点
      • 支持SQL接口
      • 支持自动维护二级索引
    • 缺点
      • SQL支持的语法不全面
      • Bug比较多
    • Hive on Hbase对比
      • Hive:SQL更加全面,但是不支持二级索引,底层通过分布式计算工具来实现
      • Phoenix:SQL相对支持不全面,但是性能比较好,直接使用HbaseAPI,支持索引实现
  • 应用

    • Phoenix适用于任何需要使用SQL或者JDBC来快速的读写Hbase的场景

    • 或者需要构建及维护二级索引场景

Phoenix的安装配置

- **需求**
  • http://phoenix.apache.org/

  • 安装部署配置Phoenix,集成Hbase

  • 分析

    • step1:上传解压安装
    • step2:修改配置,指定Hbase连接地址
    • step3:启动Phoenix,连接Hbase
  • 实现

    • 下载:http://phoenix.apache.org/download.html

    • 第一台机器上传

      cd /export/software/
      rz
      
    • 第一台机器解压

      tar -zxvf apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz -C /export/server/
      cd /export/server/
      mv apache-phoenix-5.0.0-HBase-2.0-bin phoenix-5.0.0-HBase-2.0-bin
      
    • 修改三台Linux文件句柄数

      vim /etc/security/limits.conf
      #在文件的末尾添加以下内容,*号不能去掉
      
      * soft nofile 65536
      * hard nofile 131072
      * soft nproc 2048
      * hard nproc 4096
      
    • 将Phoenix所有jar包分发到Hbase的lib目录下

      #拷贝到第一台机器
      cd /export/server/phoenix-5.0.0-HBase-2.0-bin/
      cp phoenix-* /export/server/hbase-2.1.0/lib/
      cd /export/server/hbase-2.1.0/lib/
      #分发给第二台和第三台
      scp phoenix-* node2:$PWD
      scp phoenix-* node3:$PWD
      
    • 修改hbase-site.xml,添加一下属性

      cd /export/server/hbase-2.1.0/conf/
      vim hbase-site.xml
      
      <!-- 关闭流检查,从2.x开始使用async -->
      <property>
          <name>hbase.unsafe.stream.capability.enforce</name>
          <value>false</value>
        </property>
      <!-- 支持HBase命名空间映射 -->
      <property>
          <name>phoenix.schema.isNamespaceMappingEnabled</name>
          <value>true</value>
      </property>
      <!-- 支持索引预写日志编码 -->
      <property>
        <name>hbase.regionserver.wal.codec</name>
        <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
      </property>
      <!-- 配置NS映射 -->
      <property>
        <name>phoenix.schema.isNamespaceMappingEnabled</name>
        <value>true</value>
      </property>
      
    • 同步给其他两台机器

      scp hbase-site.xml node2:$PWD
      scp hbase-site.xml node3:$PWD
      
    • 同步给Phoenix

      cp hbase-site.xml /export/server/phoenix-5.0.0-HBase-2.0-bin/bin/
      
    • 重启Hbase

      stop-hbase.sh
      start-hbase.sh
      
    • 启动Phoenix

      cd /export/server/phoenix-5.0.0-HBase-2.0-bin/
      bin/sqlline.py node1:2181
      
    • 测试

      !tables
      

在这里插入图片描述

在这里插入图片描述

  • 总结

    • 解压安装
    • 修改配置
    • 启动服务
    • 测试环境

Phoenix的语法:DDL:NS

  • http://phoenix.apache.org/language/index.html

  • 需求

    • 实现基于SQL的数据库管理:创建、切换、删除
  • 分析

    • step1:创建Namespace
    • step2:切换Namespace
    • step3:删除Namespace
  • 实现

    • 创建NS

      create schema if not exists student;
      
    • 切换NS

      use student;
      
    • 删除NS

      drop schema if exists student;
      
  • 总结

    • 基本与SQL语法一致
    • 注意:Phoenix中默认会将所有字符转换为大写,如果想要使用小写字母,必须加上双引号

Phoenix的语法:DDL:Table

  • 需求

    • 实现基于SQL的数据表管理:创建、列举、查看、删除
  • 分析

    • step1:列举当前所有的表
    • step2:创建表
    • step3:查询表信息
    • step4:删除表
  • 实现

    • 列举

      !tables
      
    • 创建

      • 语法:http://phoenix.apache.org/language/index.html#create_table

        CREATE TABLE my_schema.my_table (
            id BIGINT not null primary key, 
            date Date
        );
        
        CREATE TABLE my_table ( 
            id INTEGER not null primary key desc, 
            m.date DATE not null,
            m.db_utilization DECIMAL, 
            i.db_utilization
        ) m.VERSIONS='3';
        
        CREATE TABLE stats.prod_metrics ( 
              host char(50) not null, 
              created_date date not null,
              txn_count bigint 
              CONSTRAINT pk PRIMARY KEY (host, created_date) 
          );
        
          CREATE TABLE IF NOT EXISTS "my_case_sensitive_table"( 
              "id" char(10) not null primary key, 
              "value" integer
          ) DATA_BLOCK_ENCODING='NONE',VERSIONS=5,MAX_FILESIZE=2000000 
          split on (?, ?, ?);
        
        
          CREATE TABLE IF NOT EXISTS my_schema.my_table (
              org_id CHAR(15), 
              entity_id CHAR(15), 
              payload binary(1000),
              CONSTRAINT pk PRIMARY KEY (org_id, entity_id) 
          ) TTL=86400
        

  • 如果Hbase中没有这个表

    use default;
    create table if not exists ORDER_DTL(
        ID varchar primary key,
        C1.STATUS varchar,
        C1.PAY_MONEY float,
        C1.PAYWAY integer,
        C1.USER_ID varchar,
        C1.OPERATION_DATE varchar,
        C1.CATEGORY varchar
    );
    
  • 如果Hbase中已存在会自动关联

    create table if not exists ORDER_INFO(
        "ROW" varchar primary key,
        "C1"."USER_ID" varchar,
        "C1"."OPERATION_DATE" varchar,
        "C1"."PAYWAY" varchar,
        "C1"."PAY_MONEY" varchar,
        "C1"."STATUS" varchar,
        "C1"."CATEGORY" varchar
    ) column_encoded_bytes=0 ;
    
    • 查看

      !desc order_info;
      
    • 删除

      drop table if exists order_dtl;
      
  • 总结

    • 创建表时,必须指定主键作为Rowkey,主键列不能加列族

      create table if not exists ORDER_INFO(
      	--不能这么写
        "C1"."ROW" varchar primary key,
          "C1"."USER_ID" varchar,
        "C1"."OPERATION_DATE" varchar,
          "C1"."PAYWAY" varchar,
          "C1"."PAY_MONEY" varchar,
          "C1"."STATUS" varchar,
        "C1"."CATEGORY" varchar
      ) column_encoded_bytes=0 ;
      
      
    
    - Phoenix 4.8版本之前只要创建同名的Hbase表,会自动关联数据
    
    - Phoenix 4.8版本以后,不推荐关联表的方式
    
      - 推荐使用视图关联的方式来实现,如果你要使用关联表的方式,必须加上以下参数
    
    
    column_encoded_bytes=0 ;
    ```
    
    • 如果关联已存在的表,Rowkey字段叫做ROW,使用时必须加上双引号

      select "ROW","C1".USER_ID,"C1"."PAYWAY" from ORDER_INFO;
      

Phoenix的语法:DML:upsert

列名数值描述
Rowkey02602f66-adc7-40d4-8485-76b5632b5b53行健,编码生成
USER_ID4944191用户id
OPERATION_DATE2020-04-25 12:09:16操作时间
PAYWAY1支付方式
PAY_MONEY4070支付金额
STATUS已提交提交状态
CATEGORY手机;分类
  • 需求

    • 基于order_info订单数据实现DML插入数据
  • 分析

    • Phoenix中插入更新的命令为:upsert

      • 功能:insert + update
        • MySQL:replace
        • 如果存在就更新,如果不存在就插入
    • 语法及示例

      UPSERT INTO TEST VALUES('foo','bar',3);
      UPSERT INTO TEST(NAME,ID) VALUES('foo',123);
      UPSERT INTO TEST(ID, COUNTER) VALUES(123, 0) ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1;
      UPSERT INTO TEST(ID, MY_COL) VALUES(123, 0) ON DUPLICATE KEY IGNORE;
      
  • 实现

    • 插入一条数据

      upsert into order_info values('z8f3ca6f-2f5c-44fd-9755-1792de183845','4944191','2020-04-25 12:09:16','1','4070','未提交','电脑');
      
    • 更新USERID为123456

      upsert into order_info("ROW","USER_ID") values('z8f3ca6f-2f5c-44fd-9755-1792de183845','123456');
      
  • 总结

    • 语法类似于insert语法

    • 功能:insert + update

Phoenix的语法:DML:delete

  • 需求

    • 基于order_info订单数据实现DML删除数据
  • 分析

    • Phoenix中插入更新的命令为:delete

    • 语法及示例

      DELETE FROM TEST;
      DELETE FROM TEST WHERE ID=123;
      DELETE FROM TEST WHERE NAME LIKE 'foo%';
      
  • 实现

    • 删除USER_ID为123456的rowkey数据

      delete from order_info where USER_ID = '123456';
      
  • 总结

    • 与MySQL是一致的

## Phoenix的语法:DQL:select

  • 需求

    • 基于order_info订单数据实现DQL查询数据
  • 分析

    • Phoenix中插入更新的命令为:select

    • 语法及示例

      SELECT * FROM TEST LIMIT 1000;
      SELECT * FROM TEST LIMIT 1000 OFFSET 100;
      SELECT full_name FROM SALES_PERSON WHERE ranking >= 5.0
          UNION ALL SELECT reviewer_name FROM CUSTOMER_REVIEW WHERE score >= 8.0
      
  • 实现

    • 查询支付方式为1的数据

      select "ROW",payway,pay_money,category from order_info where payway = '1';
      
    • 查询每种支付方式对应的用户人数,并且按照用户人数降序排序

      • 分组:每、各个、不同
      • 排序:用户人数
      select
        payway,
        count(distinct user_id) as numb
      from order_info
      group by payway 
      order by numb desc;
      
    • 查询数据的第60行到66行

      --以前的写法:limit M,N
      --M:开始位置
      --N:显示的条数
      --Phoenix的写法:limit N offset M
      select * from order_info limit 6 offset 60;//总共66行,显示最后6行
      
    • 函数支持

      • http://phoenix.apache.org/language/functions.html
  • 总结

    • 基本查询与MySQL也是一致的
    • 写的时候注意数据类型以及大小写的问题即可
    • 如果遇到SQL报错,检查语法是否支持

Phoenix的使用:预分区

需求

  • Hbase命令建表

    create Ns;tbname,列族,预分区
    
    • 创建表的时候,需要根据Rowkey来设计多个分区
  • 分析

    • Phoenix也提供了创建表时,指定分区范围的语法

      CREATE TABLE IF NOT EXISTS "my_case_sensitive_table"( 
          "id" char(10) not null primary key, 
          "value" integer
      )
      DATA_BLOCK_ENCODING='NONE',VERSIONS=5,MAX_FILESIZE=2000000 split on (?, ?, ?)
      

      实现

  • 创建数据表,四个分区

    drop table if exists ORDER_DTL;
    create table if not exists ORDER_DTL(
        "id" varchar primary key,
        C1."status" varchar,
        C1."money" float,
        C1."pay_way" integer,
        C1."user_id" varchar,
        C1."operation_time" varchar,
        C1."category" varchar
    ) 
    CONPRESSION='GZ'
    SPLIT ON ('3','5','7');
    
  • 总结

    • 实现效果与命令实现的效果一致

    • 通过SQL建表语句实现

      create table() split 
      

Phoenix的使用:加盐salt

- **需求**
  • Rowkey设计的时候为了避免连续,构建Rowkey的散列,如果rowkey设计是连续的,怎么解决?

  • 分析

    • 在Phoenix创建一张盐表,写入的数据会自动进行编码写入不同的分区中

      CREATE TABLE table (
          a_key VARCHAR PRIMARY KEY, 
          a_col VARCHAR
      ) SALT_BUCKETS = 20;
      
  • 实现

    • 创建一张盐表,指定分区个数为10

      drop table if exists ORDER_DTL;
      create table if not exists ORDER_DTL(
          "id" varchar primary key,
          C1."status" varchar,
          C1."money" float,
          C1."pay_way" integer,
          C1."user_id" varchar,
          C1."operation_time" varchar,
          C1."category" varchar
      ) 
      CONPRESSION='GZ', SALT_BUCKETS=10;
      

总结

  • 由Phoenix来实现自动编码,解决Rowkey的热点问题,不需要自己设计散列的Rowkey

Phoenix的使用:视图

  • 需求

    • 直接关联Hbase中的表,会导致误删除,对数据的权限会有影响,容易出现问题,如何避免?
  • 分析

    • Phoenix中建议使用视图的方式来关联Hbase中已有的表
    • 通过构建关联视图,可以解决大部分数据查询的数据,不影响数据
    • 视图:理解为只读的表

实现

  • 创建视图,关联Hbase中已经存在的表

    create view if not exists "MOMO_CHAT"."MSG" (
        "pk" varchar primary key, -- 指定ROWKEY映射到主键
        "C1"."msg_time" varchar,
    );
    
  • 总结

    • 工作中主要构建的都是视图
    • MySQL:视图
      • Hive:外部表
      • Phoenix:视图

Phoenix的使用:JDBC

  • 需求

    • 工作中实际使用SQL,会基于程序中使用JDBC的方式来提交SQL语句,在Phoenix中如何实现?
  • 分析

    • Phoenix支持使用JDBC的方式来提交SQL语句

    • 例如:聊天分析案例中需求:查询条件为日期【年-月-日】 + 发送人ID + 接受人ID

      select 
        * 
      from "MOMO_CHAT"."MSG" 
      where 
        substr("msg_time",0,10) = '2021-03-22' 
        and "sender_account" = '17351912952' 
        and "receiver_account" = '17742251415';
      
    • 可以在代码中基于JDBC来提交SQL查询

  • 实现

    • 构建JDBC连接Phoenix

      package cn.itcast.momo_chat.service.impl;
      
      import cn.itcast.momo_chat.entity.Msg;
      import cn.itcast.momo_chat.service.ChatMessageService;
      import org.apache.phoenix.jdbc.PhoenixDriver;
      
      import java.sql.*;
      import java.util.ArrayList;
      import java.util.List;
      
      /**
       * @ClassName PhoenixChatMessageService
       * @Description TODO JDBC连接Phoenix实现数据查询
       * @Create By     Frank
       */
      public class PhoenixChatMessageService implements ChatMessageService {
          private Connection connection;
      
          public PhoenixChatMessageService() throws ClassNotFoundException, SQLException {
              try {
                  //申明驱动类
                  Class.forName(PhoenixDriver.class.getName());
      //            System.out.println(PhoenixDriver.class.getName());
                  //构建连接
                  connection = DriverManager.getConnection("jdbc:phoenix:node1,node2,node3:2181");
              } catch (ClassNotFoundException e) {
                  throw new RuntimeException("加载Phoenix驱动失败!");
              } catch (SQLException e) {
                  throw new RuntimeException("获取Phoenix JDBC连接失败!");
              }
          }
          @Override
          public List<Msg> getMessage(String date, String sender, String receiver) throws Exception {
              PreparedStatement ps = connection.prepareStatement(
                      "SELECT * FROM MOMO_CHAT.MSG T WHERE substr(\"msg_time\", 0, 10) = ? "
                              + "AND T.\"sender_account\" = ? "
                              + "AND T.\"receiver_account\" = ? ");
      
              ps.setString(1, date);
              ps.setString(2, sender);
              ps.setString(3, receiver);
      
              ResultSet rs = ps.executeQuery();
              List<Msg> msgList = new ArrayList<>();
      
              while(rs.next()) {
                  Msg msg = new Msg();
                  msg.setMsg_time(rs.getString("msg_time"));
                  msg.setSender_nickyname(rs.getString("sender_nickyname"));
                  msg.setSender_account(rs.getString("sender_account"));
                  msg.setSender_sex(rs.getString("sender_sex"));
                  msg.setSender_ip(rs.getString("sender_ip"));
                  msg.setSender_os(rs.getString("sender_os"));
                  msg.setSender_phone_type(rs.getString("sender_phone_type"));
                  msg.setSender_network(rs.getString("sender_network"));
                  msg.setSender_gps(rs.getString("sender_gps"));
                  msg.setReceiver_nickyname(rs.getString("receiver_nickyname"));
                  msg.setReceiver_ip(rs.getString("receiver_ip"));
                  msg.setReceiver_account(rs.getString("receiver_account"));
                  msg.setReceiver_os(rs.getString("receiver_os"));
                  msg.setReceiver_phone_type(rs.getString("receiver_phone_type"));
                  msg.setReceiver_network(rs.getString("receiver_network"));
                  msg.setReceiver_gps(rs.getString("receiver_gps"));
                  msg.setReceiver_sex(rs.getString("receiver_sex"));
                  msg.setMsg_type(rs.getString("msg_type"));
                  msg.setDistance(rs.getString("distance"));
      
                  msgList.add(msg);
              }
              return msgList;
          }
      
          @Override
          public void close() {
              try {
                  connection.close();
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
      
      
          public static void main(String[] args) throws Exception {
              ChatMessageService chatMessageService = new PhoenixChatMessageService();
              List<Msg> message = chatMessageService.getMessage("2021-03-22", "17351912952", "17742251415");
      
              for (Msg msg : message) {
                  System.out.println(msg);
              }
      
              chatMessageService.close();
          }
      }
      
      
      
    • 运行查看结果

在这里插入图片描述

  • 总结

    • Phoenix支持SQL
    • 支持JDBC方式提交SQL语句实现数据处理

Phoenix二级索引设计

  • 目标

    • 基于Phoenix构建Hbase二级索引并维护二级索引
  • 分析

    • 为什么需要构建二级索引?
      • 因为Hbase使用Rowkey作为唯一索引,无法满足大部分的查询走索引,导致性能较差
      • 构建二级索引:通过走两次索引代替全表扫描
    • Phoenix如何实现二级索引?
      • Phoenix底层构建了大量的协处理器,来实现二级索引的构建
  • 实现

    • step1:根据数据存储需求,创建原始数据表,将数据写入原始数据表

      rowkey:id		name		age
      
    • step2:根据数据查询需求,构建二级索引,Phoenix自动创建索引表

      create index indexName on tbName(colName);
      
      rowkey:name_id
      
    • step3:查询数据时,Phoenix根据过滤条件是否存在二级索引,优先判断走二级索引代替全表扫描

    • step4:原始数据表发生数据变化时,Phoenix会自动更新索引表的数据

  • 总结

    • 在Phoenix中二级索引实现完全由Phoenix自主实现
    • 不需要关心底层的实现,只需要使用语法创建索引即可
    • http://phoenix.apache.org/secondary_indexing.html

二级索引:全局索引设计

  • 目标

    • 了解二级索引中全局索引的设计思想
  • 分析

    • 什么是全局索引?
      • 当为某一列创建全局索引时,Phoenix自动创建一张索引表,将创建索引的这一列加上原表的rowkey作为新的rowkey
  • 实现

    • 原始数据表

      rowkey:id		name		age
      
    • 需求:根据name进行数据查询

    • 创建全局索引

      create index index01 on tbname(name);
      
    • 自动构建索引表

      rowkey:name_id		col:占位值
      
    • 查询

      • 先查询索引表:通过rowkey获取名称对应的id
      • 再查询数据表:通过id查询对应的数据
  • 总结

    • **特点:**默认只能对构建索引的字段做索引查询,如果查询中包含了不是索引的字段或者条件不是索引字段,不走索引

    • 走索引

      select name from table
        select name from table where name = value
      
      • 不走索引

        select * from table where name = value
        
    • **应用:**写少读多

      • 当原表的数据发生更新操作提交时,会被拦截
      • 先更新所有索引表,然后再更新原表

二级索引:全局索引实现

  • 目标

    • 基于Phoenix实现全局索引的测试
  • 分析

    • step1:先创建原始数据表
    • step2:基于查询条件创建索引
    • step3:实现索引查询
  • 实现

  • 基于user_id构建全局索引

    create index GBL_IDX_ORDER_DTL on ORDER_DTL(C1."user_id");
    

查看索引表

!tables

查询数据及查询计划

select "user_id" from ORDER_DTL where "user_id" = '8237476';
explain select "user_id" from ORDER_DTL where "user_id" = '8237476';
  • 强制走索引

    explain select /*+ INDEX(ORDER_DTL GBL_IDX_ORDER_DTL) */ * from ORDER_DTL where "user_id" = '8237476';
    
  • 删除索引

    drop index GBL_IDX_ORDER_DTL on ORDER_DTL;
    

    总结

  • 全局索引是最常用的基础二级索引类型

  • 索引表结构

    • rowkey:查询条件字段 + 原表rowkey
  • 应用:适合于读多写少的场景

  • 特点:如果查询条件或者查询内容中包含非索引字段,将不走索引,可以强制走索引

二级索引:覆盖索引设计

  • 目标

    • 了解二级索引中覆盖索引的设计思想
  • 分析

    • 什么是覆盖索引?
      • 在构建全局索引时,将经常作为查询条件的列放入索引表中,直接通过索引表来返回数据结果
  • 实现

    • 原始数据表

      rowkey:id		name		age  	addr  	phone
      
    • 需求:根据name进行数据查询

    • 创建全局索引

      create index index01 on tbname(name);
      
    • 自动构建索引表

      rowkey:name_id		col:占位值
      
    • 如果需求发生改变,查询name和age,上面的全局索引会失效

    • 创建全局+覆盖:include(age)

      create index index01 on tbname(name) include(age);
      
    • 自动构建索引表

      rowkey:name_id		col:age
      
      select name from table;
      select name from table where age = 20
      select name , age from table
      
  • 总结

    • **特点:**基于全局索引构建,将常用的查询结果放入索引表中,直接从索引表返回结果
    • **应用:**适合于查询条件比较固定,数据量比较小的场景下
    • 注意:不建议将大部分列都放入覆盖索引,导致索引表过大,性能降低

二级索引:覆盖索引实现

  • 目标

    • 基于Phoenix实现覆盖索引的测试
  • 分析

    • step1:先创建原始数据表
    • step2:基于查询条件创建覆盖索引
    • step3:实现索引查询
  • 实现

  • 基于user_id构建全局索引,运行通过user_id查询订单id和支付金额

    create index GBL_IDX_ORDER_DTL on ORDER_DTL(C1."user_id") INCLUDE("id", C1."money");
    
  • 查看索引表

    !tables
    
  • 查询数据

    select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
    
  • 查看执行计划

    explain select "user_id", "id", "money" from ORDER_DTL where "user_id" = '8237476';
    
      • 使用HINT强制走索引
      explain select /*+ INDEX(ORDER_DTL GBL_IDX_ORDER_DTL) */ * from ORDER_DTL where "user_id" = '8237476';
      
    • 删除索引

      drop index GBL_IDX_ORDER_DTL on ORDER_DTL;
      

总结

  • 覆盖索引是基于全局索引实现的

  • 目的是将常用的查询结果放入索引表中,直接从索引表返回数据

二级索引:本地索引设计

  • 目标

    • 了解二级索引中本地索引的设计思想
  • 分析

    • 什么是本地索引?
      • 将索引数据与对应的原始数据放在同一台机器,避免了跨网络传输,提高了写的性能
  • 实现

    • 构建索引数据时,将索引数据直接存储在原表中,用一个列族来实现
  • 总结

    • 特点
      • 即使查询数据中包含了非索引字段,也会走本地索引
      • 本地索引会修改原始数据
        • 如果构建了本地索引,不能通过Hbase的API来读写数据的,必须通过Phoenix来实现读写
      • 本地索引对盐表不生效的
    • 应用:写多读少
      • 提高构建索引时对写的性能的影响
      • 最终所有索引都是为了提高读的性能的

二级索引:本地索引实现

  • 目标

    • 基于Phoenix实现本地索引的测试
  • 分析

    • step1:先创建原始数据表
    • step2:基于查询条件创建本地索引
    • step3:实现索引查询
  • 实现

    • 关闭Hbase及Phoenix

    • 修改hbase-site.xml中Zookeeper的连接,所有Hbase节点及Phoenix的bin目录下

        <property>
          <name>hbase.zookeeper.quorum</name>
          <value>node1,node2,node3:2181</value>
        </property>
      
    • 重启Hbase和Phoenix

    • 创建本地索引

    create local index LOCAL_IDX_ORDER_DTL on ORDER_DTL("id", "status", "money", "pay_way", "user_id") ;
    
  • 删除索引

    drop index LOCAL_IDX_ORDER_DTL on ORDER_DTL;
    

总结

  • 本地索引设计:将索引与数据存储在同一台机器,提高读写的性能,通过建列族来实现的
  • 本地索引不局限于是否对列构建索引,优先走本地索引实现数据查询

二级索引:函数索引【了解】

  • 目标

    • 了解Hbase中的函数索引的概念
  • 分析

    • 本地、覆盖、全局:都是基于查询的列构建索引
    • 什么是函数索引?
      • 可以基于一个函数表达式去构建索引
  • 实现

    • 查询:过滤的条件是一个函数

      SELECT EMP_ID FROM EMP WHERE UPPER(FIRST_NAME||' '||LAST_NAME)='JOHN DOE'
      
    • 构建索引

      CREATE INDEX UPPER_NAME_IDX ON EMP (UPPER(FIRST_NAME||' '||LAST_NAME))
      
    • Hive中

      • SQL:语法

      • 函数

        • 字符串

          • substr
        • replace_regex

          • concat/concat_ws

            • concat:直接拼接每个字符串,只有有1列为null,整个结果为null
              concat(str1,str2,str3……)
            
            • concat_ws:可以指定分隔符,只要有1列不为null,整个结果不为null

              concat(分隔符,str1,str2,str3……)
              
          • instr

          • ……

        • 日期

          • 转换类:from_unix,unix_timestamp
          • 获取:year、ceil、quator、month、day、hour
        • 条件

          • if
          • case when
        • JSON处理:json_tuple,get_json_object

        • 窗口函数:重点:row_number,rank,dense_rank,lead,lag,sum

        • URL解析:parse_url_tuple

  • 总结

    • 函数索引就是基于函数表达式创建索引,当执行相同的函数表达式查询时,可以通过索引实现快速查询
    • 一般不用
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值