phoenix 与 hbase 整合,将hbase 自定义的namespace 放到phoenix 中进行完美整合

本文详细介绍HBase与Phoenix组件的整合步骤,包括配置映射、表映射及二级索引等高级特性,并探讨加盐表的应用场景和技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意: 这里以ambari 集群进行整合说明

1. 前提条件

一. ambari 集群上已经安装好了phoenix 插件以及hbase 组件

二. 保证ambari 集群的hdfs系统,zookeeper 系统,hbase 集群,phoenix 组件server ,ranger 管理权限系统 已经正常运行.

 

 2. 配置hbase的namespace映射为phoenix数据库; (到hbase 服务的cofig 配置选项卡下选择"自定义 hbase-site.xml" 配置中添加一下内容)
2.1 修改hbase-site.xml,增加下面配置项并重启bhase服务,修改后hbase namespace会映射为数据库的schema .

 

property>
  <name>phoenix.schema.isNamespaceMappingEnabled</name>
  <value>true</value>
</property>
<property>
  <name>phoenix.schema.mapSystemTablesToNamespace</name>
  <value>true</value>
</property>

 

以上是大部分博客或者简书都说到的,都需要配置的内容,但是在实际操作过程中发现此时hbase 和phoenix 只是针对系统namespace 是起到作用的,但是自定义的namespace  在phoenix 中是怎么也找不着(我这里是这样的),经过两天的查找资料以及查看phoenix 的官网(http://phoenix.apache.org/views.html)关于hbase 与phoenix 进行整合的讲解方法,最终得到了答案 .

 

需要进行下面至关重要的一步:

3.进行hbase 与phoenix 的映射 表关系

参考网址: https://community.hortonworks.com/questions/215750/how-to-map-a-phoenix-viewtable-with-a-different-na.html

先在phoenix shell  命令行,使用命令查看:

命令:

select DISTINCT TABLE_SCHEM from SYSTEM.CATALOG;

     1). 若发现 只有一个schem 那说明只是系统的 ;

      2). 若发现不知一个schem  的话,说明上面的配置已经完全找到hbase 的namespace ,其下面的操作都不需要在进行操作了,直接就进行关于phoenix 与hbase 的表进行映射吧.

 

若你出现方框中的第一个情况,在phoenix shell  命令行直接进行下面这条sql 语句:

CREATE SCHEMA IF NOT EXISTS   "test"; 

   注意:

       1. 这里"test" 是我集群中hbase 的namespace 中一个测试库,请换成自己的hbase 集群 的namespace;

       2. phoenix shell 的sql 语句中有大小写区分,默认是使用字母大写,使用双引号就不会转换成大写; 

    当添加schema 成功之后,然后再执行第一条sql 命令查看 schema ,会发现我们已经成功添加了一个schema  .然后按照 常规操作建立phoenix 与 hbase 建立映射表 关系 

以上就是hbase与phoenix 组件进行整合细节操作 .


4. phoenix 一些扩展内容

 下面的内容是参考网址( https://www.jianshu.com/p/91decdd7fc5d ) 的内容

     我觉得写的是非常好的,但是没有进行实践过,希望大家可以学习一下.

 

加盐表

1. 什么是加盐?

在密码学中,加盐是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。而Phoenix中加盐是指对pk对应的byte数组插入特定的byte数据。

2. 加盐能解决什么问题?

加盐能解决HBASE读写热点问题,例如:单调递增rowkey数据的持续写入,使得负载集中在某一个RegionServer上引起的热点问题。

3. 怎么对表加盐?

在创建表的时候指定属性值:SALT_BUCKETS,其值表示所分buckets(region)数量, 范围是1~256。

CREATE TABLE table (key VARCHAR PRIMARY KEY, col VARCHAR) SALT_BUCKETS = 8;

4. 加盐的原理是什么?

加盐的过程就是在原来key的基础上增加一个byte作为前缀,计算公式如下:

new_row_key = (++index % BUCKETS_NUMBER) + original_key

下图展示了自增rowkey通过加盐被打散写入到各个region中的过程

5. 一个表“加多少盐合适”?

当可用block cache的大小小于表数据大小时,较优的slated bucket是和region server数量相同,这样可以得到更好的读写性能。

当表的数量很大时,基本上会忽略blcok cache的优化收益,大部分数据仍然需要走磁盘IO。比如对于10个region server集群的大表,可以考虑设计64~128个slat buckets。

6. 加盐时需要注意

创建加盐表时不能再指定split key。

太大的slated buckets会减小range查询的灵活性,甚至降低查询性能。

References

https://phoenix.apache.org/salted.html

https://zh.wikipedia.org/wiki/%E7%9B%90_(%E5%AF%86%E7%A0%81%E5%AD%A6)

https://community.hortonworks.com/questions/26269/how-many-salt-buckets-should-i-use-for-my-phoenix.html

 


二级索引

一.概要

目前HBASE只有基于字典序的主键索引,对于非主键过滤条件的查询都会变成扫全表操作,为了解决这个问题Phoenix引入了二级索引功能。然而此二级索引又有别于传统关系型数据库的二级索引,本文将详细描述Phoenix中二级索引功能、用法和原理,希望能够对大家在业务技术选型时起到一些帮助作用。

二.二级索引

示例表如下(为了能够容易通过HBASE SHELL对照表内容,我们对属性值COLUMN_ENCODED_BYTES设置为0,不对column family进行编码):

CREATE TABLE  TEST (   ID VARCHAR NOT NULL  PRIMARY KEY,   COL1 VARCHAR,   COL2 VARCHAR  ) COLUMN_ENCODED_BYTES=0;

upsert into TEST values('1', '2', '3');

1. 全局索引

全局索引更多的应用在读较多的场景。它对应一张独立的HBASE表。对于全局索引,在查询中检索的列如果不在索引表中,默认的索引表将不会被使用,除非使用hint。

创建全局索引:

CREATE INDEX IDX_COL1 ON TEST(COL1)

通过HBASE SHELL观察生成的索引表IDX_COL1。我们发现全局索引表的RowKey存储了索引列的值和原表RowKey的值,这样编码更有利于提高查询的性能。

hbase(main):001:0> scan 'IDX_COL1'ROW                        COLUMN+CELL 2\x001                    column=0:_0, timestamp=1520935113031, value=x1 row(s) in 0.1650 seconds

实际上全局索引的RowKey将会按照如下格式进行编码

 

SALT BYTE: 全局索引表和普通phoenix表一样,可以在创建索引时指定SALT_BUCKETS或者split key。此byte正是存储着salt。TENANT_ID: 当前数据对应的多租户ID。INDEX VALUE: 索引数据。PK VALUE: 原表的RowKey。

2. 本地索引

因为本地索引和原数据是存储在同一个表中的,所以更适合写多的场景。对于本地索引,查询中无论是否指定hint或者是查询的列是否都在索引表中,都会使用索引表。

创建本地索引:

create local index LOCAL_IDX_COL1 ON TEST(COL1);

通过HBASE SHELL观察表'TEST', 我们可以看到表中多了一行column为L#0:_0的索引数据。

hbase(main):001:0> scan 'TEST'ROW                        COLUMN+CELL \x00\x002\x001            column=L#0:_0, timestamp=1520935997600, value=_0 1                         column=0:COL1, timestamp=1520935997600, value=2 1                         column=0:COL2, timestamp=1520935997600, value=3 1                         column=0:_0, timestamp=1520935997600, value=x2 row(s) in 0.1680 seconds

本地索引的RowKey将会按照如下格式进行编码

 

REGION START KEY : 当前row所在region的start key。加上这个start key的好处是,可以让索引数据和原数据尽量在同一个region, 减小IO,提升性能。INDEX ID : 每个ID对应不同的索引表。TENANT ID :当前数据对应的多租户ID。INDEX VALUE: 索引数据。PK VALUE: 原表的RowKey。

3. 覆盖索引

覆盖索引的特点是把原数据存储在索引数据表中,这样在查询到索引数据时就不需要再次返回到原表查询,可以直接拿到查询结果。

创建覆盖索引:

create  index IDX_COL1_COVER_COL2 on TEST(COL1) include(COL2);

通过HBASE SHELL 查询表IDX_COL1_COVER_COL2, 我们发现include的列的值被写入到了value中。

hbase(main):003:0> scan 'IDX_COL1_COVER_COL2'ROW                   COLUMN+CELL 2\x001               column=0:0:COL2, timestamp=1520943893821, value=3 2\x001               column=0:_0, timestamp=1520943893821, value=x1 row(s) in 0.0180 seconds

对于类似select col2 from TEST where COL1='2'的查询,查询一次索引表就能获得结果。其查询计划如下:

+--------------------------------------------------------------------------------------+-----------------+----------------+---+|                                         PLAN                                         | EST_BYTES_READ  | EST_ROWS_READ  | E |+--------------------------------------------------------------------------------------+-----------------+----------------+---+| CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER IDX_COL1_COVER_COL2 ['2']  | null            | null           | n |+--------------------------------------------------------------------------------------+-----------------+----------------+---+

4. 函数索引

函数索引的特点是能根据表达式创建索引,适用于对查询表,过滤条件是表达式的表创建索引。例如:

//创建函数索引CREATE INDEX CONCATE_IDX ON TEST (UPPER(COL1||COL2))//查询函数索引SELECT * FROM TEST WHERE UPPER(COL1||COL2)='23'

三.什么是Phoenix的二级索引?

Phoenix的二级索引我们基本上已经介绍过了,我们回过头来继续看Phoenix二级索引的官方定义:Secondary indexes are an orthogonal way to access data from its primary access path。简单理解为,在主访问路径(通过row key访问)上发生正交的一种方法,更清楚的应该描述为:索引列访问和row key访问产生交集时的一种索引方法。我们来通过一个例子说明:

1. 对表TEST的COL1创建全局索引

CREATEINDEXIDX_COL1ONTEST(COL1);

2. 对于如下查询必将发生FULL SCAN

select*fromTESTwhereCOL1='2';

以上查询的查询计划如下:

+----------------------------------------------------------------+-----------------+----------------+--------------+|                              PLAN                              | EST_BYTES_READ  | EST_ROWS_READ  | EST_INFO_TS  |+----------------------------------------------------------------+-----------------+----------------+--------------+| CLIENT1-CHUNK PARALLEL1-WAY ROUND ROBIN FULL SCAN OVER TEST  |null|null|null||     SERVER FILTER BY COL1 ='2'|null|null|null|+----------------------------------------------------------------+-----------------+----------------+--------------+

3. 对于以下查询将会形成点查。因为二级索引是RowKey的交集。

select * from TEST where id='1' and COL1='2'

查询计划如下

+---------------------------------------------------------------------------------------------+-----------------+-------------+|                                            PLAN                                             | EST_BYTES_READ  | EST_ROWS_RE |+---------------------------------------------------------------------------------------------+-----------------+-------------+| CLIENT 1-CHUNK 1 ROWS 203 BYTES PARALLEL 1-WAY ROUND ROBIN POINT LOOKUP ON 1 KEY OVER TEST  | 203             | 1           ||     SERVER FILTER BY COL1 = '2'                                                             | 203             | 1           |+---------------------------------------------------------------------------------------------+-----------------+-------------+

对于2中所描述的查询为什么会发生FULL SCAN? 正如Phoenix二级索引官方定义的一样,因为“没有和RowKey列的查询发生正交关系”,除非使用Hint强制指定索引表。

四.索引Building

Phoenix的二级索引创建有同步和异步两种方式。

在执行CREATE INDEX IDX_COL1 ON TEST(COL1)时会进行索引数据的同步。此方法适用于数据量较小的情况。

异步build索引需要借助MR,创建异步索引语法和同步索引相差一个关键字:ASYNC。

//创建异步索引CREATE INDEX ASYNC_IDX ON DB.TEST (COL1) ASYNC//build 索引数据${HBASE_HOME}/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool --schema DB --data-table TEST --index-table ASYNC_IDX  --output-path ASYNC_IDX_HFILES

五.索引问题汇总

1. 创建同步索引超时怎么办?

在客户端配置文件hbase-site.xml中,把超时参数设置大一些,足够build索引数据的时间。

 

2. 索引表最多可以创建多少个?

建议不超过10个

3. 为什么索引表多了,单条写入会变慢?

索引表越多写放大越严重。写放大情况可以参考下图。

 

References

https://phoenix.apache.org/secondary_indexing.html

https://community.hortonworks.com/articles/61705/art-of-phoenix-secondary-indexes.html


MR在Ali-Phoenix上的使用

一.MR在Phoenix上的用途

利用MR对Phoenix表(可带有二级索引表)进行Bulkload入库, 其原理是直接生成主表(二级索引表)的HFILE写入HDFS。相对于走API的数据导入方式,不仅速度更快,而且对HBASE集群的负载也会小很多。目前云HBASE上的Phoenix支持以下数据源的Bulkload工具:

CsvBulkLoadTool

JsonBulkLoadTool

RegexBulkLoadTool

ODPSBulkLoadTool(待上线)

利用MR Building二级索引。当主表数据量较大时,可以通过创建异步索引,使用MR快速同步索引数据。

二.如何访问云HBASE的HDFS?

由于云HBASE上没有MR,需要借助外部的计算引擎(自建的HADOOP集群或者EMR),而使用外部的计算引擎的首先面临的问题是,如何跨集群访问HDFS。

由于云HBASE的HDFS端口默认是不开的,需要联系工作人员开通。

端口开通以后,要想顺利的访问HDFS是HA配置的云HBASE集群,需要向工作人员获取云HBASE的主备(emr-header-1,emr-header-2)namenode host/IP。参考如下配置模板,设置hadoop客户端配置文件:

core-site.xml

hdfs-site.xml

验证访问云HBASE HDFS

hadoop dfs -ls hdfs://emr-cluster/

三.BULKLOAD PHOENIX表

1. 由于要和云HBASE通信,所以客户端的依赖的hbase-protocol.jar需要是1.1.x版本。可以使用链接:http://central.maven.org/maven2/org/apache/hbase/hbase-protocol/1.1.1/hbase-protocol-1.1.1.jar 下载。

2. 以EMR访问云HBASE为例。EMR集群需要把云HBASE HDFS的emr-cluster 相关配置和当前EMR的HDFS配置合在一起形成新的配置文件,单独存放在一个目录(${conf-dir})下。通过yarn命令的--config参数指定新的配置目录,使这些配置文件放在CLASSPATH最前面覆盖掉当前EMR集群hadoop_conf_dir下的配置,以便bulkload程序能识别到云HBASE HA的HDFS URL。

3. 执行BULKLOAD命令

yarn --config ${CONF_DIR} jar ${PHOENIX_HOME}/phoenix-${version}-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool --table "TABLENAME" --input "hdfs://emr-header-1.cluster-55090:9000/tmp/test_data"  --zookeeper "zk1,zk2,zk3" --output "hdfs://emr-cluster/tmp/tmp_data"

注意: --output 配置的是云HBASE的临时文件,这样直接把生成的HFILE存储在云HBASE的HDFS上,后续的只有简单的move操作。否则,如果生成在EMR集群还需要走网络发送到云HBASE HDFS上。

 

 

 

<think>好的,用户的问题是如何通过HBase访问Phoenix数据,需要配置方法和示例代码。首先,我需要回忆HBasePhoenix的关系。Phoenix是构建在HBase之上的SQL层,提供SQL查询功能。用户可能已经知道Phoenix可以通过SQL操作HBase数据,但现在想反过来,用HBase的API访问Phoenix处理过的数据。接下来,我需要确定两者的数据存储结构是否兼容。Phoenix在创建表时,会使用特定的命名空间和列族,比如将列映射为HBase的列限定符。因此,HBase直接访问Phoenix表的数据是可行的,但需要注意表名、列族和列名的对应关系。然后,配置方面可能需要确保HBasePhoenix的版本兼容。用户提到的引用中提到了Phoenix5.0.0-5.1.2,所以需要确认对应的HBase版本,比如2.1.x是否兼容。另外,集群部署时,两者的JAR包需要正确放置,比如将Phoenix的clientjar添加到HBase的类路径中,这样HBase的API才能正确解析Phoenix的数据结构。 用户可能需要具体的步骤,比如如何配置环境,如何通过HBase Shell或Java API访问数据。例如,在HBase Shell中使用scan命令查看Phoenix创建的表,或者用Java API读取数据。需要注意Phoenix的表在HBase中的存储方式,比如命名空间可能为SYSTEM或用户自定义,列族通常是0等。 示例代码部分,用户可能需要JavaAPI的示例,展示如何连接HBase并读取Phoenix表的数据。需要确保代码中正确指定表名、列族和列名,并处理可能的版本问题。同时,需要提醒用户注意依赖的版本匹配,避免出现类冲突或方法不兼容的情况。 另外,用户引用中提到Bulk Load和Spark集成,可能用户有大数据量处理的需求,可以建议使用BulkLoad方式将数据导入HBase,再通过Phoenix查询,或者反之。但当前问题集中在HBase访问Phoenix数据,所以需要专注于直接的访问方法。最后,需要验证步骤,比如通过HBaseShell列出表,查看数据是否存在,或者编写简单的Java程序读取数据。同时,常见问题如类路径错误、表不存在或权限问题也需要提及,帮助用户排查。</think>### HBase访问Phoenix数据的配置实现方法 HBaseApache Phoenix的集成主要通过**共享底层存储**实现,Phoenix的表数据实际存储在HBase中。以下是具体配置步骤和示例代码: --- #### 一、环境配置要点 1. **版本匹配** PhoenixHBase需版本兼容(如Phoenix 5.1.2对应HBase 2.1.x)[^2]。 2. **部署Phoenix客户端库** 将Phoenix的`phoenix-client-hbase-2.1-5.1.2.jar`复制到HBase的`lib`目录: ```bash cp /path/to/phoenix-client.jar $HBASE_HOME/lib/ ``` 3. **重启HBase集群** 确保所有节点加载Phoenix依赖库。 --- #### 二、通过HBase Shell访问Phoenix表 1. **查看Phoenix创建的表** Phoenix表默认存储在`SYSTEM`命名空间或用户自定义命名空间: ```bash hbase> list_namespace_tables 'SYSTEM' # 查看系统表 hbase> scan 'SYSTEM:STATS' # 示例:扫描Phoenix元数据表 ``` 2. **访问用户表** 假设Phoenix中创建了表`MY_TABLE`: ```sql CREATE TABLE MY_TABLE (ID INTEGER PRIMARY KEY, NAME VARCHAR); ``` 在HBase Shell中对应的操作为: ```bash hbase> scan 'MY_TABLE' # 直接扫描表 ``` --- #### 三、Java API访问示例 ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Table; public class HBasePhoenixAccess { public static void main(String[] args) throws Exception { Configuration config = HBaseConfiguration.create(); config.set("hbase.zookeeper.quorum", "hadoop001:2181"); try (Connection conn = ConnectionFactory.createConnection(config)) { Table table = conn.getTable(TableName.valueOf("MY_TABLE")); Get get = new Get(Bytes.toBytes("rowkey1")); // Phoenix的ROWKEY为二进制格式 Result result = table.get(get); // 解析列值(Phoenix列名转换为HBase列限定符) byte[] nameValue = result.getValue( Bytes.toBytes("0"), // Phoenix默认列族为0 Bytes.toBytes("NAME") // 对应Phoenix列名 ); System.out.println("NAME: " + Bytes.toString(nameValue)); } } } ``` --- #### 四、关键注意事项 1. **列名列族映射** Phoenix的列默认映射到HBase的列族`0`,列名转换为全大写[^3]。 2. **数据类型兼容性** Phoenix的`VARCHAR`在HBase中存储为`STRING`类型,需确保编解码一致。 3. **命名空间同步** 若Phoenix表创建在自定义命名空间(如`MY_SCHEMA`),HBase中需通过`MY_SCHEMA:TABLE_NAME`访问。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值