Phoenix+Hbase二级索引

入门小站

使用的软件版本,注意软件版本很重要,很重要

apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz
hadoop-2.9.2.tar.gz
hbase-2.0.5-bin.tar.gz

Hbase中通过非rowkey查询数据查询速度会很慢

为什么需要二级索引

在Hbase中要想精确查询一条数据所以必须使用rowkey,如果不通过rowkey查询数据,就必须逐行逐列的比较(即全表扫描),效率很低. 实际业务中需要通过多个维度快速查询数据. 例如查询用户的时候可能需要通过用户名,姓名,邮箱,手机号查询,但是把这种多维度的查询字段都放到rowkey中,显然是不可能的(灵活性不高,roekey的长度也是有限制的),因此二级索引的应用场景就应运而生,Phoenix已经提供了对HBase的二级索引支持支持。

二级索引分类

  • Global indexing 全局索引,适用于读多写少的场景
使用Global indexing在写数据的时候开销很大,因为所有对数据表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),都会引起索引表的更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。
  • Local indexing 本地索引,适用于写多的场景
与Global indexing一样,Phoenix会自动判定在进行查询的时候是否使用索引。使用Local indexing时,索引数据和数据表的数据存放在相同的服务器中,这样避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。使用Local indexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Global indexing不同。对于Local Indexing,一个数据表的所有索引数据都存储在一个单一的独立的可共享的表中。
  • immutable indexing 不可变索引,适用于数据只增加不更新,而且按时间顺序先后循序存储.
不可变索引的存储方式是write one,append only。当在Phoenix使用create table语句时指定IMMUTABLE_ROWS = true表示该表上创建的索引将被设置为不可变索引。Phoenix默认情况下如果在create table时不指定IMMUTABLE_ROW = true时,表示该表为mutable。不可变索引分为Global immutable index和Local immutable index两种。
  • mutable indexing 可变索引,适用于数据有增删的的场景
Phoenix默认情况下创建的索引是可变索引,除非指定 IMMUTABLE_ROW=true

开启Hbase对二级索引的支持

vim vim hbase-2.3.1/conf/hbase-site.xml

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

user表创建索引

>create table user1(
    id varchar(10) primary key,
    f.name varchar(100),
    f.pass varchar(100),
    f.grp varchar(10),
    f.type varchar(5),
    f.types varchar(2),
    f.code varchar(10),
    f.uname varchar(20),
    f.email varchar(20),
    f.factory varchar(10),
    f.depart varchar(10),
    f.region varchar(10)
)column_encoded_bytes=0;
> create index user_name on user(name);
//查询索引
> !indexes user

user表删除索引

> drop index user_name on user;

实战

  • create index user_name on user; //默认可变索引
//创建索引
> create index user_name on user;

//*这样查询是不会走索引的
> select *  from user where name='rumenz';
> explain select * from user where name='rumenz'; 

//FULL SCAN OVER USER SERVER FILTER BY F.NAME =
//查询字段和索引字段保持一致就可以用到索引

> select name from user where name='rumenz';
> explain select name from user where name='rumenz';
//CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER USER_NAME SERVER FILTER BY FIRST KEY ONLY 
  • create local index user_name on user1(name); //创建本地索引
//*这样查询就会走索引
> select *  from user where name='rumenz';
> explain select * from user where name='rumenz'; 
//使用到了索引
//ROUND ROBIN RANGE SCAN OVER USER1
  • converted index //相当于一个联合索引
> create index user_name1 on user1(name) include(pass);
//只有当name,pass在查询字段出现时,才会用到索引:比如
//select name from user1 where name=''或者 pass='';
//select pass from user1 where name=''或者 pass='';
//select name,pass from user1 where name=''或者 pass='';
  • 在select和column_name之间加上/*+ Index(<表名> <index名>)*/,通过这种方式强制使用索引。
> select /*+ index(user1,USER_NAME) */ pass from user1 where name='xxx';
//1.如果pass是索引那么从索引表查询.
//2.如果pass不是索引,那么会进行全表扫描会很慢.

重建索引

> alter index USER_NAME on user1 rebuild;

索引性能调优

1. index.builder.threads.max 
创建索引时,使用的最大线程数。 
默认值: 10。

2. index.builder.threads.keepalivetime 
创建索引的创建线程池中线程的存活时间,单位:秒。 
默认值: 60

3. index.writer.threads.max 
写索引表数据的写线程池的最大线程数。 
更新索引表可以用的最大线程数,也就是同时可以更新多少张索引表,数量最好和索引表的数量一致。 
默认值: 10

4. index.writer.threads.keepalivetime 
索引写线程池中,线程的存活时间,单位:秒。
默认值:60
 

5. hbase.htable.threads.max 
每一张索引表可用于写的线程数。 
默认值: 2,147,483,647

6. hbase.htable.threads.keepalivetime 
索引表线程池中线程的存活时间,单位:秒。 
默认值: 60

7. index.tablefactory.cache.size 
允许缓存的索引表的数量。 
增加此值,可以在写索引表时不用每次都去重复的创建htable,这个值越大,内存消耗越多。 
默认值: 10

8. org.apache.phoenix.regionserver.index.handler.count 
处理全局索引写请求时,可以使用的线程数。 
默认值: 30

阅读 450

rumenz.com

53 声望
3 粉丝
0 条评论

rumenz.com

53 声望
3 粉丝
宣传栏