Phoenix05 索引介绍


1. 介绍

在HBase中,只有一个单一的按照字典序排序的 rowKey 索引,当使用 rowKey 来进行数据查询的时候速度较快,但是如果不使用rowKey 来查询的话就会使用 filter 来对全表进行扫描,很大程度上降低了检索性能。而 Phoenix 提供了二级索引技术来应对这种使用rowKey 之外的条件进行检索的场景。

Phoenix 支持两种类型的索引技术:Global Indexing 适用 读频繁Local Indexing 适用 写频繁 ,这两种索引技术分别适用于不同的业务场景(主要是偏重于读还是偏重于写)。下面分别对这两种索引技术简单使用一下,具体性能方面没有进行测试。

索引官方文档地址: http://phoenix.apache.org/secondary_indexing.html

2. Global Indexing(读频繁)

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

2.1 配置hbase-site.xml

使用 Global Indexing 的话需要配置 hbase-site.xml,在 HBase 集群的每个 regionserver 节点的 hbase-site.xml 中加入如下配置并重启HBase集群。

<property>
    <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>

2.2 创建表

进入phoenix的CLI的界面创建company表。

create table company(id varchar primary key, name varchar, address varchar);

2.3 查看company表索引

!indexes company

2.4 创建索引

对company 表的 name 字段创建索引,索引名为 my_index 。

create index my_index on company(name);

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

!tables

select * from my_index;

该表中会有 2 个字段,其中 :ID 是自动创建的,其实就是 HBase 中的主键 RowKey,0:NAME 是我们刚刚手动创建的。

2.5 插入数据

在company表中添加测试数据。

upsert into company(id, name, address) values('001', 'dimensoft', 'nanjing');

2.6 查询数据

查询company表数据

select name,address from company where name='dimensoft';

查询索引表my_index

select * from my_index;

从HBase的CLI界面查看索引表MY_INDEX

scan 'MY_INDEX'

2 个索引字段 NAME 和 ID 的值被合并为索引表 MY_INDEX 的 rowKey,\x000 是十六进制表示,转换为字符串是空格。

# 这样的查询语句是不会用到索引表的
# name 字段虽然是索引字段但是 address 字段并不是索引字段!
select name,address from company where name='dimensoft';

# 也就是说需要查询出来的字段必须都是索引字段如下:
select name from company where name='dimensoft';

2.7 使用索引

如果希望使用索引表进行查询的话可以使用以下三种方式来解决这个问题:

2.7.1 强制使用索引表

在进行查询的时候通过sql语句强制使用索引查询。

SELECT /*+ INDEX(company my_index) */ name,address FROM company WHERE name = 'dimensoft';

这样的查询语句会导致二次检索数据表,第一次检索是去索引表中查找符合 name 为 dimensoft 的数据,这时候发现 address 字段并不在索引字段中,会去 company 表中第二次扫描,因此只有当用户明确知道符合检索条件的数据较少的时候才适合使用,否则会造成全表扫描,对性能影响较大。

2.7.2 创建 covered index

  • 创建索引的时候指定一个covered字段,先删除my_index索引
drop index my_index on company;
  • 创建covered index
create index my_index on company(name) include(address);

使用这种方式创建的所有会导致 address 字段的值被拷贝到索引中,缺点就是会导致索引表大小有一定的增加。

查询索引表 my_index 数据。

select * from my_index;

这里的数据是自动同步过来的,可以发现 address 字段的值也被存储了。

从 HBase的CLI 中查看 MY_INDEX 表数据会发现比不使用 include 的时候多了一行数值,并且里面包含了address 字段的值。

scan 'MY_INDEX'

这个时候就再使用下面的查询语句就会使用到索引来进行查询了。

select name,address from company where name='dimensoft';

2.7.3 使用Local Indexing创建索引

与 Global Indexing 不同,当使用 Local Indexing 的时候即使查询的所有字段都不在索引字段中时也会用到索引进行查询(这是由Local Indexing自动完成的)

3. Local Indexing (写频繁)

Local indexing 适用于写操作频繁的场景。与 Global indexing 一样,Phoenix 会自动判定在进行查询的时候是否使用索引。使用Local indexing 时,索引数据和数据表的数据是存放在相同的服务器中的避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。使用 Local indexing 的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟 Global indexing 不同。一个数据表的所有索引数据都存储在一个单一的独立的可共享的表中。在读数据的时候因为存储数据的 region 的位置无法预测导致性能有一定损耗。

3.1 配置hbase-site.xml

使用 Local Indexing 的话需要配置 hbase-site.xml,在HBase集群的 master 节点的 hbase-site.xml 中添加如下配置并重启 HBase 集群。

配置这个参数的目的是确保数据表与索引表协同定位。

<property>
    <name>hbase.master.loadbalancer.class</name>
    <value>org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer</value>
</property>
<property>
    <name>hbase.coprocessor.master.classes</name>
    <value>org.apache.phoenix.hbase.index.master.IndexMasterObserver</value>
</property>

为了支持数据区域合并时本地索引区域合并,您需要在所有区域服务器的hbase-site.xml中添加以下参数,并重新启动。(适用于Phoenix 4.3+版本)

<property>
    <name>hbase.coprocessor.regionserver.classes</name>
    <value>org.apache.hadoop.hbase.regionserver.LocalIndexMerger</value>
</property>

3.2 创建表

进入phoenix的CLI的界面创建company表。

create table company2(id varchar primary key, name varchar, address varchar);

3.3 查看company表索引

!indexes company2

3.4 创建索引

对company表的name字段创建索引,索引名为my_index。

 create local index my_index on company2(name);

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

通过squirrel来查看company2的索引字段

3.5 插入数据

在company表中添加测试数据。

upsert into company2(id, name, address) values('001', 'dimensoft', 'nanjing');

3.6 查询数据

查看company表数据以及索引表my_index数据。

select * from company2;

select * from my_index2;

3.7 查看表中的数据

查看刚刚插入的数据,索引数据被放进了hbase 表中

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


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
 上一篇
Spark累加器与广播变量介绍 Spark累加器与广播变量介绍
1. 共享变量通常,当传递给Spark操作(如map或reduce)的函数在远程集群节点上执行时,它可以在函数中使用的所有变量的单独副本上工作。这些变量被复制到每个机器,并且远程机器上的变量的更新不会传播回驱动程序。在任务之间支持一般的,读
2017-04-07
下一篇 
Squirrel GUI 连接 Phoenix Squirrel GUI 连接 Phoenix
1. 介绍本文介绍使用 Squirrel GUI 客户端来连接 Phoenix,就像 MySQL 使用 Navicat for MySQL,Oracle 使用 Pl/sql developer 一样,在进行一些数据库操作的时候能够更加的直观
2017-03-15
  目录