HBase(十四)SQL引擎Phoenix

Phoenix介绍

1.什么是Phoenix

Phoenix是一个HBase的开源SQL引擎。你可以使用标准的JDBC API代替HBase客户端API来创建表,插入数据,查询你的HBase数据。

2.Phoenix底层原理

Phoenix框架将命令行上键入的sql语句翻译成hbase指令,然后hbase用翻译好的指令去操作集群,执行完之后给客户端反馈结果。

3.安装部署

  • 需要先安装好hbase集群,phoenix只是一个工具,只需要在一台机器上安装就可以了,这里我们选择node02服务器来进行安装一台即可

1、下载安装包

2、上传解压

  • 将安装包上传到node02服务器的/kkb/soft路径下,然后进行解压

3.安装

4.配置环境变量

5.重启hbase集群

  • 记得要先启动hadoop集群、zookeeper集群

  • ==node01执行==以下命令来重启hbase的集群

4、验证是否成功

  • 1、在phoenix/bin下输入命令, 进入到命令行,接下来就可以操作了

    ==node02执行==以下命令,进入phoenix客户端

5、Phoenix使用

1、 批处理方式

  • 1、node02执行以下命令创建user_phoenix.sql文件
    • 内容如下

  • 2、node02执行以下命令,创建user_phoenix.csv数据文件

  • 3、创建user_phoenix_query.sql文件

  • 4、执行sql语句

2、 命令行方式

  • 执行命令

  • 退出命令行方式,phoenix的命令都需要一个感叹号

  • 查看phoenix的帮助文档,显示所有命令

2.1表的映射

  • 1、建立employee的映射表

    进入hbase客户端,创建一个普通表employee,并且有两个列族 company 和family
    node01执行以下以下命令进入hbase 的shell客户端

  • 2、数据准备

  • 3、建立hbase到phoenix的映射表

    node02进入到phoenix的客户端,然后创建映射表

    说明

    在建立映射表之前要说明的是,Phoenix是大小写敏感的,并且所有命令都是大写

    如果你建的表名没有用双引号括起来,那么无论你输入的是大写还是小写,建立出来的表名都是大写的

    如果你需要建立出同时包含大写和小写的表名和字段名,请把表名或者字段名用双引号括起来

  • 4、查询映射表数据

3.JDBC

  • 创建maven工程并导入jar包

  • 代码开发

6.Phoenix构建二级索引

1、为什么需要用二级索引?

  • 对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询。如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄。

  • 对于较大的表,全表扫描的代价是不可接受的。但是,很多情况下,需要从多个角度查询数据。

    • 例如,在定位某个人的时候,可以通过姓名、身份证号、学籍号等不同的角度来查询
    • 要想把这么多角度的数据都放到rowkey中几乎不可能(业务的灵活性不允许,对rowkey长度的要求也不允许)。
    • 所以需要secondary index(二级索引)来完成这件事。secondary index的原理很简单,但是如果自己维护的话则会麻烦一些。
    • 现在,Phoenix已经提供了对HBase secondary index的支持。

2、Phoenix Global Indexing And Local Indexing

2.1 Global Indexing

  • Global indexing,全局索引,适用于读多写少的业务场景。
  • 使用Global indexing在写数据的时候开销很大,因为所有对数据表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),都会引起索引表的更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。
  • 在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。
    • 在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。

2.2 Local Indexing

  • Local indexing,本地索引,适用于写操作频繁以及空间受限制的场景。
  • 与Global indexing一样,Phoenix会自动判定在进行查询的时候是否使用索引。
  • 使用Local indexing时,索引数据和数据表的数据存放在相同的服务器中,这样避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。
  • 使用Local indexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Global indexing不同。对于Local Indexing,一个数据表的所有索引数据都存储在一个单一的独立的可共享的表中。

3、Immutable index And Mutable index

3.1 immutable index

  • immutable index,不可变索引,适用于数据==只增加不更新并且按照时间先后顺序存储==(time-series data)的场景,如保存日志数据或者事件数据等。
  • 不可变索引的存储方式是write one,append only。
  • 当在Phoenix使用create table语句时指定IMMUTABLE_ROWS = true表示该表上创建的索引将被设置为不可变索引。
  • 不可变索引分为Global immutable index和Local immutable index两种。
  • Phoenix默认情况下如果在create table时不指定IMMUTABLE_ROW = true时,表示该表为mutable。

3.2 mutable index

  • mutable index,可变索引,适用于数据有增删改的场景。
  • Phoenix默认情况创建的索引都是可变索引,除非在create table的时候显式地指定IMMUTABLE_ROWS = true。
  • 可变索引同样分为Global mutable index和Local mutable index两种。

4、配置HBase支持Phoenix二级索引

4.1 修改配置文件

  • 如果要启用phoenix的二级索引功能,需要修改配置文件hbase-site.xml
  • 注意:
  • vim hbase-site.xml

4.2 重启hbase

  • 完成上述修改后重启hbase集群使配置生效。

5、实战

5.1 在phoenix中创建表

  • 首先,在phoenix中创建一个user table
  • node02执行以下命令,进入phoenix客户端,并创建表

5.2 导入测试数据

  • 将课件当中的user50w.csv 这个文件上传到node02的/kkb/install/phoenixsql 这个路径下
    该CSV文件中有50万条记录
  • node02执行以下命令,导入50W的测试数据

5.3 Global Indexing的二级索引测试

5.3.1 正常查询一条数据所需的时间
  • 在为表USER创建secondary index之前,先看看查询一条数据所需的时间
    在node02服务器,进入phoenix的客户端,然后执行以下sql语句,查询数据,查看耗费时间

​ 可以看到,对名为cookie_id的列进行按值查询需要6秒左右。

​ 我们可以通过explain来查看执行计划
​ EXPLAIN(语句的执行逻辑及计划):

​ 由此看出先进行了全表扫描再通过过滤器来筛选出目标数据,显示这种查询方式效率是很低的。

5.3.2 给表USER创建基于Global Indexing的二级索引
  • 进入到phoenix的客户端,然后执行以下命令创建索引
  • 在cookie_id列上面创建二级索引:

  • 再次执行查询"cookie_id"=’99738fd1-2084-44e9’的数据记录

    此时:查询速度由10秒左右减少到了毫秒级别。

    注意:select所带的字段必须包含在覆盖索引内

    EXPLAIN(语句的执行逻辑及计划):

    可以看到使用到了创建的索引USER_COOKIE_ID_INDEX。

5.3.3 以下查询不会用到索引表
  • 虽然cookie_id是索引字段,但age不是索引字段,所以不会使用到索引

  • 也可以通过EXPLAIN查询语句的执行逻辑及计划

  • 同理要查询的字段不是索引字段,也不会使用到索引表。

5.4 Local Indexing的二级索引测试

5.4.1 正常查询一条数据所需的时间
  • 在为表USER创建secondary index之前,先看看查询一条数据所需的时间

  • 可以看到,对名为user_id的列进行按值查询需要3秒左右。

  • EXPLAIN(语句的执行逻辑及计划):

  • 由此知道先进行了全表扫描再通过过滤器来筛选出目标数据,显示这种查询方式效率是很低的。

5.4.2 给表USER创建基于Local Indexing的二级索引
  • 在user_id列上面创建二级索引:

  • 查看当前所有表会发现多一张USER_USER_ID_INDEX索引表,查询该表数据。

  • 再次执行查询"user_id"=’371e963d-c-487065’的数据记录

  • 可以看到,对名为user_id的列进行按值查询需要0.7秒左右。

  • EXPLAIN(语句的执行逻辑及计划):

​ 查看执行计划,没有执行全表扫描,效率更高了

​ 此时:查询速度由3秒左右减少到了毫秒级别。

那如果查询的字段不包含在索引表中,又如何呢?

EXPLAIN(语句的执行逻辑及计划):

​ 可以看到使用到了创建的索引USER_USER_ID_INDEX.

5.5 如何确保query查询使用Index

  • 要想让一个查询使用index,有三种方式实现。
5.5.1 创建 covered index
  • 如果在某次查询中,查询项或者查询条件中包含除被索引列之外的列(主键MY_PK除外)。
  • 默认情况下,该查询会触发full table scan(全表扫描),但是使用covered index则可以避免全表扫描。创建包含某个字段的覆盖索引,创建方式如下:

  • 查看当前所有表会发现多一张USER_COOKIE_ID_AGE_INDEX索引表,查询该表数据。

  • 查询数据

5.5.2 在查询中提示其使用index
  • 在select和column_name之间加上/*+ Index(<表名> <index表名>)*/,通过这种方式强制使用索引。

如果age是索引字段,那么就会直接从索引表中查询
如果age不是索引字段,那么将会进行全表扫描,所以当用户明确知道表中数据较少且符合检索条件时才适用,此时的性能才是最佳的。

5.5.3 使用本地索引 (创建Local Indexing 索引)
  • 详细见上面

5.6 索引重建

  • Phoenix的索引重建是把索引表清空后重新装配数据。

5.7 删除索引

  • 删除某个表的某张索引:
    语法 drop index 索引名称 on 表名
    例如:

​ 如果表中的一个索引列被删除,则索引也将被自动删除

​ 如果删除的是覆盖索引上的列,则此列将从覆盖索引中被自动删除。

6、索引性能调优

  • 一般来说,索引已经很快了,不需要特别的优化。
  • 这里也提供了一些方法,让你在面对特定的环境和负载的时候可以进行一些调优。下面的这些需要在hbase-site.xml文件中设置,针对所有的服务器。

Views: 19