Phoenix 在 HBase 生态系统中占据了非常重要的地位,本文主要包括以下几方面内容:

  • Phoenix 介绍

  • CDH HBase 集成 Phoenix

  • 使用 Phoenix 创建 HBase 二级索引

  • Phoenix 索引类型介绍

Phoenix 介绍

Phoenix 是构建在 HBase 之上的高效的 SQL 引擎,同时具备 OLTP 和 OLAP 能力,作为 HBase 生态系统中非常重要的组件,重点的特性包括:

  • 底层存储基于 HBase,并提供一套标准的 JDBC API 作为 HBase SQL 层;

  • 支持标准 SQL,以及完整 ACID 事务特性;

  • 为 HBase 提供了二级索引解决方案;

此外,Phoenix 还和很多其他组件做了集成,比如 Spark、Hive、Flume 等。Phoenix 与 HBase 集成,其最大的特点就是为 HBase 提供了二级索引,后文会重点介绍。下图是 Phoenix 的基本架构:

CDH HBase 集成 Phoenix

版本说明

  • 针对 CDH 平台,目前 Phoenix 官网主要提供了 Phoenix-4.14.0-cdh5.{11, 12, 13, 14}.2 版本的安装包,包括源码包、二进制 tar 安装包以及 parcel 安装包,可以根据自己集群 CDH 版本选择合适的 Phoenix-4.14.0 CDH 安装包,建议选择 parcel 包,下载地址:http://phoenix.apache.org/download.html;

  • 高版本 CDH 安装 Phoenix 可以参考:产品 | Cloudera正式宣布在CDH中支持Apache Phoenix

  • 低版本 CDH 可以选择安装 CLABS_Phoenix,最大支持 Phoenix 4.7.0,parcel 包下载地址:http://archive.cloudera.com/cloudera-labs/phoenix/parcels/

  • 此外,用户还可以自行编译适合自己的Phoenix版本。

安装

首先到官网下载适合自己环境的 Parcel 安装包,并发布到 httpd 服务:

[root@hadoop-01 /var/www/html/phoenix/4.14.0]$ ll
total 300524
-rw-r--r-- 1 root root 307722240 Feb  3 19:30 APACHE_PHOENIX-4.14.0-cdh5.11.2.p0.3-el7.parcel
-rw-r--r-- 1 root root       178 Feb  3 19:28 APACHE_PHOENIX-4.14.0-cdh5.11.2.p0.3-el7.parcel.sha512
-rw-r--r-- 1 root root      5081 Feb  3 19:30 manifest.json

然后配置成 CDH 远程 Parcel 存储库 url:

接下来下载,分配,激活完成安装即可。

配置

安装完 Phoenix 后,需要做一些必要配置才能使用 Phoenix,CDH HBase 配置界面配置如下两处:

1. hbase-site.xml 的 HBase 服务高级配置代码段(安全阀)

2. hbase-site.xml 的 HBase 客户端高级配置代码段(安全阀)

添加如下参数配置:

<!-- 二级索引支持 -->
<property><name>hbase.regionserver.wal.codec</name><value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property><!-- 命名空间映射开启,Phoenix4.8.0开始支持 -->
<property><name>phoenix.schema.isNamespaceMappingEnabled</name><value>true</value>
</property>
<property><name>phoenix.schema.mapSystemTablesToNamespace</name><value>true</value>
</property>

然后,按照提示重启HBase服务并重新部署客户端配置即可。

命令行使用

CDH 安装后环境变量都已经配置好了,可以直接使用 phoenix-sqlline.py,如下:

[root@hadoop-01 ~]$ phoenix-
phoenix-performance.py  phoenix-psql.py         phoenix-sqlline.py      phoenix-utils.py

执行 phoenix-sqlline.py 初始化使用 Phoenix:

然后我们查看下 HBase 中 Phoenix 的系统表:

hbase(main):003:0> list
SYSTEM:CATALOG
SYSTEM:FUNCTION
SYSTEM:LOG
SYSTEM:MUTEX
SYSTEM:SEQUENCE
SYSTEM:STATS

接下来看一下如何在 Phoenix 中创建 HBase 表的二级索引。

使用 Phoenix 创建 HBase 二级索引

映射已存在的 HBase 表

1. 查看 HBase 表

当前 HBase 中存在一张操作日志表 ns1000:operate_log,数据量近280w,包括14个字段,如下:

hbase(main):017:0> count 'ns1000:operate_log', INTERVAL => 100000
...
2799827 row(s) in 173.4200 seconds=> 2799827
hbase(main):018:0> scan 'ns1000:operate_log', LIMIT => 1
ROW                                                          COLUMN+CELL                                                                                                                                                                    \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:appVersion, timestamp=1538216707892, value=2.22.0                                                                                                                     \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:area, timestamp=1538216707892, value=\xE6\xB1\x9F\xE5\x8C\x97\xE5\x8C\xBA                                                                                             \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:authId, timestamp=1538216707892, value=                                                                                                                               \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:city, timestamp=1538216707892, value=\xE9\x87\x8D\xE5\xBA\x86\xE5\xB8\x82                                                                                             \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:imei, timestamp=1538216707892, value=AF36147F-8106-47F0-B58F-A3FB75DBE325                                                                                             \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:lat, timestamp=1538216707892, value=29.577587127685547                                                                                                                \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:lon, timestamp=1538216707892, value=106.50493621826172                                                                                                                \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:memberType, timestamp=1538216707892, value=0                                                                                                                          \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:mobileManufacturer, timestamp=1538216707892, value=iPhone                                                                                                             \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:mobileModel, timestamp=1538216707892, value=iPhone 6 Plus                                                                                                             \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:province, timestamp=1538216707892, value=\xE9\x87\x8D\xE5\xBA\x86\xE5\xB8\x82                                                                                         \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:systemType, timestamp=1538216707892, value=1                                                                                                                          \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:systemVersion, timestamp=1538216707892, value=12.0                                                                                                                    \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:time, timestamp=1538216707892, value=1538216707720
1 row(s) in 0.0460 seconds

2. Phoenix 中创建与 namespace 名称一致的 schema

0: jdbc:phoenix:> create schema if not exists "ns1000";
No rows affected (0.012 seconds)

3. Phoenix 中创建视图,并查询数据及条数

0: jdbc:phoenix:> use "ns1000";
No rows affected (0.021 seconds)
0: jdbc:phoenix:> create view "operate_log"(
. . . . . . . . > "pk" varchar primary key,
. . . . . . . . > "f"."appVersion" varchar,
. . . . . . . . > "f"."city" varchar,
. . . . . . . . > "f"."lat" varchar,
. . . . . . . . > "f"."lon" varchar,
. . . . . . . . > "f"."memberType" varchar,
. . . . . . . . > "f"."time" varchar);
No rows affected (6.555 seconds)
0: jdbc:phoenix:> !tables
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
| TABLE_CAT  | TABLE_SCHEM  |  TABLE_NAME  |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME  | REF_GENERATION  | INDEX_STATE  | IMMUTABLE_ROWS  | SALT_BUCKETS  | MULTI_TENANT  | VIEW_STATEMENT  | VIEW_TYPE  | INDEX_ |
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
|            | SYSTEM       | CATALOG      | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | FUNCTION     | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | LOG          | SYSTEM TABLE  |          |            |                            |                 |              | true            | 32            | false         |                 |            |        |
|            | SYSTEM       | SEQUENCE     | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | STATS        | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | ns1000       | operate_log  | VIEW          |          |            |                            |                 |              | false           | null          | false         |                 | MAPPED     |        |
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
0: jdbc:phoenix:> !columns "operate_log";
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
| TABLE_CAT  | TABLE_SCHEM  |  TABLE_NAME  | COLUMN_NAME  | DATA_TYPE  | TYPE_NAME  | COLUMN_SIZE  | BUFFER_LENGTH  | DECIMAL_DIGITS  | NUM_PREC_RADIX  | NULLABLE  | REMARKS  | COLUMN_DEF  | SQL_DATA_TYPE  | SQL_DATETIME_SUB  | CHAR_O |
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
|            | ns1000       | operate_log  | pk           | 12         | VARCHAR    | null         | null           | null            | null            | 0         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | appVersion   | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | city         | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | lat          | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | lon          | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | memberType   | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | time         | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
0: jdbc:phoenix:> select * from "operate_log" limit 1;
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
|           pk           | appVersion  | city  |         lat         |         lon         | memberType  |      time      |
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
1538216707720  | 2.22.0      | 重庆市   | 29.577587127685547  | 106.50493621826172  | 0           | 1538216707720  |
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
1 row selected (0.115 seconds)
0: jdbc:phoenix:> select count(*) from "operate_log";
+-----------+
| COUNT(1)  |
+-----------+
| 2799827   |
+-----------+
1 row selected (3.848 seconds)

4. 根据字段 time 进行时间范围查询:

0: jdbc:phoenix:> select count(*) from "operate_log" where "f"."time" between '1538216707720' and '1538223834000';
+-----------+
| COUNT(1)  |
+-----------+
| 5883      |
+-----------+
1 row selected (5.241 seconds)

这种情况下,基本上查询都在 5s 左右。

这里还要有两点说明:

  • Phoenix 会自动将表名、字段名都转成大写,如果要区分大小写使用双引号括起来即可。

  • 这里我们创建的是视图,相当于外部表,也可以 create table 创建表,视图的特点是删除时不会删除 HBase 表,但是视图创建的二级索引不会自动更新,如果要实时更新的话,只能使用 create table,然后通过 Phoenix jdbc 的方式写入数据,只有通过 Phoenix 写,然后用 Phoenix 实现的协处理器才能实现实时更新的索引。

使用 Phoenix 创建二级索引

1. 使用 Phoenix 对 time 字段创建索引

0: jdbc:phoenix:> create index index_operate_log_time on "operate_log" ("f"."time");
2,799,827 rows affected (95.814 seconds)

2. 再次根据 time 字段做范围查询

00: jdbc:phoenix:> select count(*) from "operate_log" where "f"."time" between '1538216707720' and '1538223834000';
+-----------+
| COUNT(1)  |
+-----------+
| 5883      |
+-----------+
1 row selected (0.049 seconds)

这里基本上查询都在 50 ms 左右。这就是通过 Phoenix 的二级索引带来的性能提升。

Phoenix 索引类型介绍

Phoenix 提供了多种索引类型,包括覆盖索引、函数索引,以及全局索引与本地索引等,具体介绍如下。

Covered Indexes(覆盖索引)

覆盖索引是在索引表中直接存储某些常用字段,当查询时所有字段仅涉及索引表中包含的字段时,则无需再在基于 rowkey 索引的数据表中查询,提高了查询的效率。

比如,我们在operate_log 表 "f"."time" 列上创建一个索引,并在索引中包含 "f"."lat", "f"."lon" 列:

0: jdbc:phoenix:> create index index_operate_log_time2 on "operate_log" ("f"."time") INCLUDE("f"."lat", "f"."lon");
2,799,827 rows affected (133.367 seconds)

这样我们做类似如下查询时就可以直接走索引表,以提高查询性能:

0: jdbc:phoenix:> select "f"."lat", "f"."lon" from "operate_log" where "f"."time" between '1538216707720' and '1538223834000' limit 10;

Functional Indexes(函数索引)

函数索引是在 Phoeinx 4.3 版本之后新增的,它使得索引的建立不仅仅只限于基于列,而可以使用任意的表达式来创建索引,在查询时,如出现相同的表达式查询条件,则会自动优先检索索引表。

比如,我们在operate_log 表上基于 substr ( "f"."time", 1, 10) 创建一个索引:

0: jdbc:phoenix:> create index index_operate_log_time3 on "operate_log" (substr("f"."time", 1, 10));
2,799,827 rows affected (94.74 seconds)

这样创建索引后,我们就可以使用相同表达式走索引表进行查询优化了,比如:

0: jdbc:phoenix:> select count(*) from "operate_log" where substr("f"."time", 1, 10) between '1538216707' and '1538223834';
+-----------+
| COUNT(1)  |
+-----------+
| 5886      |
+-----------+
1 row selected (0.059 seconds)

Global Indexes(全局索引)

上面的覆盖索引和函数索引都属于全局索引,也是 Phoenix 默认的索引创建模式。

全局索引将索引表和数据表分开存储,如以上例子中都会创建一张新的索引表,因此每条数据和其索引数据可能会分布在不同的数据节点上,数据表的添加、删除和修改都会更新相关的索引表,所以写入数据时由于额外的网络开销会带来较大的性能消耗。而查询数据的时候,Phoenix 会通过索引表来快速低损耗的获取数据。因此全局索引更适合读多写少的使用场景。

Local Indexes(本地索引)

本地索引与全局索引相反,在 4.8.0 版本之后会将索引数据以特定的列簇存储在同一张数据表中,并通过特定的 rowkey 设置,将每条数据及其索引数据存储在同一 region 中,因此在数据写入时防止了额外的网络开销,而在读取数据时因无法提前判断索引数据的准确位置,则会在所有的 region 中检索索引数据,而非常影响读取性能。所以本地索引更适合于写多读少的使用场景。

本地索引只要在原来索引创建时增加 local 关键字即可,比如:

0: jdbc:phoenix:> create local index index_operate_log_time on "operate_log" ("f"."time");

总结

Phoenix 是构建在 HBase 之上的 SQL 层,不仅能够提供标准的 SQL 查询,还能够为 HBase 提供二级索引能力,在 HBase 使用场景中应用非常广泛。Phoenix 二级索引主要分为全局索引和本地索引,全局索引适合那些读多写少的场景,本地索引更适合那些写多读少的场景。判断是否走索引可以 explain SQL 查看具体执行计划。

参考:

1. HBase集成Phoenix,构建Phoenix view和table的区别

2. 如何使用Phoenix在CDH的HBase中创建二级索引

3. 产品 | Cloudera正式宣布在CDH中支持Apache Phoenix

往期推荐

1、HBase最佳实践 | 聊聊HBase核心配置参数
2、Apache Hudi:剑指数据湖的增量处理框架
3、Hadoop社区比 Ozone 更重要的事情
4、MapReduce Shuffle 和 Spark Shuffle 结业篇

HBase 集成 Phoenix 构建二级索引实践相关推荐

  1. 利用phoenix建立二级索引查询hbase,大神请无视

    利用phoenix建立二级索引查询hbase phoenix的简单介绍 phoenix,中文译为"凤凰",很美的名字.Phoenix是由saleforce.com开源的一个项目,后 ...

  2. MySQL的一级索引和二级索引介绍,HBase中提到的二级索引【笔记自用】

    1.一级索引 索引和数据存储在一起,都存储在同一个B+tree中的叶子节点.一般主键索引都是一级索引. 2.二级索引 二级索引树的叶子节点存储的是主键而不是数据.也就是说,在找到索引后,得到对应的主键 ...

  3. Phoenix创建二级索引

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

  4. HBase建表高级属性,hbase应用案例看行键设计,HBase和mapreduce结合,从Hbase中读取数据、分析,写入hdfs,从hdfs中读取数据写入Hbase,协处理器和二级索引

    1. Hbase高级应用 1.1建表高级属性 下面几个shell 命令在hbase操作中可以起到很到的作用,且主要体现在建表的过程中,看下面几个create 属性 1. BLOOMFILTER 默认是 ...

  5. hbase基于solr配置二级索引

    一.概述 Hbase适用于大表的存储,通过单一的RowKey查询虽然能快速查询,但是对于复杂查询,尤其分页.查询总数等,实现方案浪费计算资源,所以可以针对hbase数据创建二级索引(Hbase Sec ...

  6. Phoenix: 验证二级索引和主表数据是否一致

    Phoenix 4.12之后才有这个工具, 就是跑一个MapReduce对比主表和数据表是否一致. 找到的不一致的行写入到文件或者 PHOENIX_INDEX_SCRUTINY 表中. 命令如下: h ...

  7. 【收藏】HBase集成Phoenix实现类SQL操作hbase

    https://blog.51cto.com/kinglab/2447715?source=drt

  8. 阿里云EMR异步构建云HBase二级索引

    一.非HA EMR构建二级索引 云HBase借助Phoenix实现二级索引功能,对于Phoenix二级索引的详细介绍可参考https://yq.aliyun.com/articles/536850?s ...

  9. hbase组合rowkey_「从零单排HBase 11」HBase二级索引解决方案

    HBase一个令人惋惜的地方,就是不支持二级索引.因此,社区有了很多补充方案来填补HBase的二级索引能力的缺陷. 今天,我们就来看看有哪些二级索引方案,通过对比各个方案的优缺点,并结合我们的具体场景 ...

最新文章

  1. 设计模式之享元模式学习笔记
  2. 十年研发经验嵌入式工程师书籍推荐
  3. P4512 【模板】多项式除法
  4. Aux函数java,verse.aux
  5. 形容PHP程序员的语句,形容程序员的句子
  6. C语言之字符串探究(九):空格去除——trim系列
  7. iOS SwiftUI 开发实机测试 TextField 不显示字
  8. 【python|opencv】读取/保存图片,路径含有中文问题解放方案(opencv 无法读取/保存图片)
  9. 走心!15年程序员老兵的40条编程技巧,先收藏了!
  10. ISO/IEC 27002:2022中文版
  11. JS动态添加Html
  12. 利用Python进行数据分析(Ⅳ)
  13. 计算机符号的名字,空格符号怎么打 游戏名字空格怎么打
  14. 一个2022本科生的秋招总结 (大疆、Arm、小米、荣耀、美团、联发科等)
  15. 让游戏沉浸感炸裂的实时3D音效技术原理与实践(上)
  16. 手机相机好坏测试软件,专业相机测试 画质表现均为中上等_手机评测-中关村在线...
  17. 百度离线地图开发,node实现地图瓦片下载
  18. ️ 后羿采集器——最良心的爬虫软件
  19. Android 身份证号码、手机号码以及邮箱账号 的中间隐藏显示
  20. redhat各版本和下载地址

热门文章

  1. 中国旋转开关行业市场供需与战略研究报告
  2. 【Python+C#】手把手搭建基于Hugging Face模型的离线翻译系统(如果你想,也可以在线)
  3. react源码中的fiber架构
  4. 我的世界java内存不足_我的世界:使用启动器开MC,提示内存过大?我教你怎么解决...
  5. UBOOT I2C读写详解(基于mini2440)
  6. 小米2s刷原生安卓_小米2/2S刷原生安卓Android4.4ROM刷機教程
  7. 我收藏的短线操作技巧
  8. golang中匿名组合
  9. mysql1044错误代码_mysql出现1044错误怎么办
  10. iOS前期OC训练OC_10Block