Phonenix4.9 (添加二级索引,新版本本地索引表变更) hbase1.25的集成测试

1.安装habse 1.25    

2.下载并且解压  Phonenix 4.9  (所有节点)  

 我用的是:apache-phoenix-4.9.0-HBase-1.2-bin.tar.gz 


3. 将Phonenix   的    lib     中的所有jar包   拷贝到hbase的里面   (所有节点)

(二级索引测试)

(补充:2017-8-15日):

hbase-site.xml  中添加:(每个节点,phonenix4.8 以下版本 配置不同 ,网上自己找)


<property>
  <name>hbase.regionserver.wal.codec</name>
  <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
<property>
  <name>hbase.region.server.rpc.scheduler.factory.class</name>
  <value>org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory</value>
  <description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<property>
  <name>hbase.rpc.controllerfactory.class</name>
  <value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value>
  <description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>


4.把hbase  中  conf    里面的    hbase-site.xml  文件拷贝到   Phonenix 中的    bin    目录中  (所有节点)


5.重新启动hbase


6.开启Phonenix    : # Phonenix/bin/sqlline.py   zkserver01:2181   (任意hbase集群节点,后面跟的是zk的一个节点,我的是slaver3:2800)


效果:

Setting property: [incremental, false]
Setting property: [isolation, TRANSACTION_READ_COMMITTED]
issuing: !connect jdbc:phoenix:slaver3:2800 none none org.apache.phoenix.jdbc.PhoenixDriver
Connecting to jdbc:phoenix:slaver3:2800
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/phoenix4.9.0/phoenix-4.9.0-HBase-1.2-client.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hadoop2.73/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
17/08/11 09:17:51 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Connected to: Phoenix (version 4.9)
Driver: PhoenixEmbeddedDriver (version 4.9)
Autocommit status: true
Transaction isolation: TRANSACTION_READ_COMMITTED
Building list of tables and columns for tab-completion (set fastconnect to true to skip)...
87/87 (100%) Done
Done
sqlline version 1.2.0


7.#!tables    

能看到很多表

0: jdbc:phoenix:slaver3:2800> !tables
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+------------+
| TABLE_CAT  | TABLE_SCHEM  | TABLE_NAME  |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME  | REF_GENERATION  | INDEX_STATE  | IMMUTABLE_ROWS  | SALT_BUCKE |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+------------+
|            | SYSTEM       | CATALOG     | SYSTEM TABLE  |          |            |                            |                 |              | false           | null       |
|            | SYSTEM       | FUNCTION    | SYSTEM TABLE  |          |            |                            |                 |              | false           | null       |
|            | SYSTEM       | SEQUENCE    | SYSTEM TABLE  |          |            |                            |                 |              | false           | null       |
|            | SYSTEM       | STATS       | SYSTEM TABLE  |          |            |                            |                 |              | false           | null       |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+-----


8.操作练习

0: jdbc:phoenix:slaver3:2800>  CREATE TABLE MY_TABLE (id BIGINT not null primary key,dt CHAR(15));
No rows affected (1.35 seconds)
0: jdbc:phoenix:slaver3:2800> UPSERT INTO my_table values(12,'abc');
1 row affected (0.109 seconds)
0: jdbc:phoenix:slaver3:2800> UPSERT INTO my_table values(13,'bcd');
1 row affected (0.023 seconds)
0: jdbc:phoenix:slaver3:2800> select * from my_table;
+-----+------+
| ID  |  DT  |
+-----+------+
| 12  | abc  |
| 13  | bcd  |
+-----+------+
2 rows selected (0.098 seconds)
0: jdbc:phoenix:slaver3:2800> !quit
Closing: org.apache.phoenix.jdbc.PhoenixConnection


这里是在hbase shell中查看


[root@slaver3 bin]# cd /home/hbase1.25/bin/
[root@slaver3 bin]# ./hbase shell
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/hbase1.25/lib/phoenix-4.9.0-HBase-1.2-client.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hbase1.25/lib/phoenix-4.9.0-HBase-1.2-hive.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hbase1.25/lib/phoenix-4.9.0-HBase-1.2-pig.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hbase1.25/lib/phoenix-4.9.0-HBase-1.2-thin-client.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hbase1.25/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hadoop2.73/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version 1.2.5, rd7b05f79dee10e0ada614765bb354b93d615a157, Wed Mar  1 00:34:48 CST 2017


hbase(main):001:0> list
TABLE                                                                                                                                                                           
MY_TABLE                                                                                                                                                                        
SYSTEM.CATALOG                                                                                                                                                                  
SYSTEM.FUNCTION                                                                                                                                                                 
SYSTEM.SEQUENCE                                                                                                                                                                 
SYSTEM.STATS                                                                                                                                                                    
ScalaTest                                                                                                                                                                       
TestScores                                                                                                                                                                      
hbase_test                                                                                                                                                                      
student                                                                                                                                                                         
9 row(s) in 0.2800 seconds


=> ["MY_TABLE", "SYSTEM.CATALOG", "SYSTEM.FUNCTION", "SYSTEM.SEQUENCE", "SYSTEM.STATS", "ScalaTest", "TestScores", "hbase_test", "student"]


hbase(main):006:0> scan 'MY_TABLE'
ROW                                           COLUMN+CELL                                                                                                                       
 \x80\x00\x00\x00\x00\x00\x00\x0C             column=0:DT, timestamp=1502414575468, value=abc                                                                                   
 \x80\x00\x00\x00\x00\x00\x00\x0C             column=0:_0, timestamp=1502414575468, value=x                                                                                     
 \x80\x00\x00\x00\x00\x00\x00\x0D             column=0:DT, timestamp=1502414588554, value=bcd                                                                                   
 \x80\x00\x00\x00\x00\x00\x00\x0D             column=0:_0, timestamp=1502414588554, value=x                                                                                     
2 row(s) in 0.0510 seconds


二级索引测试:


案例:(4.7 及其一下版本,4.8在后面写到)

1
> create table company( id varchar primary key, name varchar, address varchar);
查看company表索引
[Bash shell]  纯文本查看  复制代码
?
1
> !indexes company

2.3 创建索引


对company表的name字段创建索引,索引名为my_index。
[Bash shell]  纯文本查看  复制代码
?
1
> create local index my_index on company(name);
查看当前所有表会发现多一张MY_INDEX索引表,查询该表数据。
通过squirrel来查看company的索引字段。

从HBase的CLI界面查看当前所有表。


《重要提示:》

phonenix4.8开始 会将“本地索引表”一同合并到原表中;(后面有实例,下面这个是4.7以下的版本,能在hbase中看到本地索引表)

[Bash shell]  纯文本查看  复制代码
?
1
> list
高能预警:这里的索引表并不叫MY_INDEX,而是叫_LOCAL_IDX_COMPANY,但是在Phoenix的CLI中进行数据查询的时候仍然是使用MY_INDEX进行查询,应该是做了映射。


2.4 插入数据


在company表中添加测试数据。
[Bash shell]  纯文本查看  复制代码
?
1
> upsert into company( id , name, address) values( '001' , 'dimensoft' , 'nanjing' );


2.5 查询数据


查看company表数据以及索引表my_index数据。
[Bash shell]  纯文本查看  复制代码
?
1
2
> select * from company;
> select * from my_index;
从HBase的CLI界面查看索引表_LOCAL_IDX_COMPANY。
[Bash shell]  纯文本查看  复制代码
?
1
> scan '_LOCAL_IDX_COMPANY'

3个索引字段_INDEX_ID、NAME和ID的值被合并为索引表的rowKey,其中_INDEX_ID并没有值(\x000是十六进制表示,转换为字符串是空格)。



phonenix 4.8 版本以上  local  index变更:


phoenix有全局索引以及本地索引(可变与不可变等其它的且不谈),全局索引理解应该比较简单,如果让我自己去实现Hbase的索引应该想到的也是全局索引这种方式。本地索引适用于写比较频繁,储存空间受限的情况。

Local indexing targets write heavy, space constrained use cases.

phoenix-4.8.x的本地索引与之前版本的实现方式完全不同,在官网中也没有比较详细的说明(感觉phoenix的文档跟不上版本更新)。以4.8版本为分水岭,分别说一下新旧版本的两种不同实现方式。

2. 本地索引前置条件

实现本地索引需要考虑以下3个方面的因素:

  1. 索引数据与原表数据需要位于同一regionserver(colocation),这是为了性能而考虑,可以避免不必要的网络传输。同时,它也是条件2的前置条件:意味着数据region和索引region都以原子性的方式被同一个regionserver打开(要么一起提供服务,要么一起offline)。
  2. 一致性:指的是索引表与原表可以被原子更新数据,有两种方式:1)使用事务 ;2)索引表与原表共享相同的wal同时使用MVCC机制。
  3. 需要考虑客户端如何使用索引数据:如果本地索引是保存在一个单独的表中,那么客端直接进行scan等一些操作,但如果索引数据隐藏在原数据region当中,那么就需要另外的机制去保障如何从原数据region中访问到索引数据。

3. 旧版本实现方式

4.8以前版本的实现方式与全局索引有点相似(索引数据与原表数据分离),不同的是本地索引有自己的split逻辑,具体的细节可以参考华为hbase二级索引的实现原理,这种实现方式的特点有:

  1. 由一个单独的表去保存本地索引数据
  2. 原表以及索引表各自拥有自己的WAL,这意味着一致性得不到保障,有可能原表数据多于索引数据,也有可能相反。
  3. 使用balancer来尽量保证colocation,但只能提供一个很弱的保证,最坏的情况下它将会失去原表数据与索引数据co-locate特性。
  4. 使用本地索引就像对一个常规的phoenix进行操作,例如查询的时候根据查询条件可以快速定位到索引数据处于哪个region上(这点比4.8的实现方式好)。

4. 4.8版本实现方式

4.1 特点

引用官网的描述:

From 4.8.0 onwards we are storing all local index data in the separate shadow column families in the same data table

这里说明了索引的数据是与原表数据储存在同一个表的,不过索引数据是一个独立的”阴影列族”,在网上是搜索不到这个概念的,个人理解是因为这个一列族客观是存在的,但使用时对用户不可见,这种方式的特点有:

  1. 这种存储特性使得colocation得到强保证,因为原表数据与索引数据的RowKey都在同一个范围内,使得它们会位于同一个region中。
  2. 因为原数据与索引数据保存在同一个region,所以它们共享同一个WAL与MVCC标志,使得原子性也得到保证:当插入一行记录时,会同时解析出其中的索引数据并附加到本次的插入,所以,实际插入的行=业务数据+索引。
  3. 索引数据的生成以及读取都依赖于原表以及索引表(索引表已经是一个逻辑表),原因在下面介绍本地索引RowKey的组成会说明。
  4. 这种实现方式不需要对hbase作任何改变,最主要的是不用再去维护region的split以及merge(以前的实现方式需要phoenix自己实现逻辑以保证split/merge后索引数据与原数据依然在同一个region中)

4.2 索引构成

1.创建一个测试

CREATE TABLE USER (ID BIGINT NOT NULL PRIMARY KEY, NAME VARCHAR  NULL,AGE INTEGER  NULL, ADDRESS VARCHAR NULL) ;
 
 
  • 1
  • 1

2.为测试表创建一个本地索引

CREATE LOCAL INDEX USER_IDX ON USER(NAME);
 
 
  • 1
  • 1

3.插入一条记录

UPSERT INTO USER(ID,NAME,AGE,ADDRESS) VALUES(1,'name1',11,'china');
 
 
  • 1
  • 1

4.进入hbase shell并scan

这里写图片描述

观察scan结果,只upsert了一条记录,却出现了2 row(s),那是因为多了一行索引数据,可以看到第一行记录即为索引数据: 
\x00\x00name1\x00\x80\x00\x00\x00\x00\x00\x00\x01

分析一下索引的组成部分,上面以3种颜色表示不同的部分:

\x00\x00:这是代表索引的编号,如果再创建多一个索引,那么会变成\x00\x01 
name1\x00:索引列的值,后面的\x00其实是空格,不知是不是为了起标记作用 
\x80\x00\x00\x00\x00\x00\x00\x01:这串就是RowKey即ID值了,可以参考scan正面的记录值。

注意,上面的分析是基于一个region的情况,如果原表是加盐表,RowKey=加盐前缀+ID,而索引数据也会一样在索引编号前面加上同样的加盐前缀,这样可以保证了索引与原表数据保存在同一个桶(region)中,保证了colocate特性。这里的加盐前缀其实相当于该region的starRowKey。其中还涉及了很多实现细节,例如当region进行split时会怎么样,可以去参考一下奇虎360Hbase二级索引的实现原理。

4.3 不足之处

  1. 当确定查询条件进行查询,此时是无法确定我们要检索的数据位于哪一个region上面,根据上面所分析的索引构成,索引还有一部分是加盐前缀(region的startRowKey),这个部分就是查询时无法确定的,所以当一个查询请求到达时,所有region都会响应,这会带来额外的开销。相比于全局索引或者旧版本的本地索引实现方式,由于是一个单独的表来保存索引数据,所以根据查询条件可以快速定位到索引数据所在的region.
  2. 使用本地索引一般都是先根据查询条件获取到数据rowkey,然后再根据rowkey到原表查询其它列的详细信息,所以,每一次查询都包含了scan以及seek操作,这也是它不适用于读频繁的原因之一。

4. 参考

https://phoenix.apache.org/secondary_indexing.html 
https://issues.apache.org/jira/browse/PHOENIX-1734



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值