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

温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。

Fayson的github: https://github.com/fayson/cdhproject

提示:代码块部分可以左右滑动查看噢

1.文档编写目的


对于HBase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询。如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄。对于较大的表,全表扫描的代价是不可接受的。

但是,很多情况下,需要从多个角度查询数据。例如,在定位某个人的时候,可以通过姓名、身份证号、学籍号等不同的角度来查询,要想把这么多角度的数据都放到rowkey中几乎不可能(业务的灵活性不允许,对rowkey长度的要求也不允许)。

所以,需要secondary index来完成这件事。secondary index的原理很简单,即通过索引表来实现,但是如果自己维护的话则会麻烦一些。在很早的版本中,Phoenix就已经提供了对HBase secondary index的支持。

Fayson在前面的文章《Cloudera Labs中的Phoenix》和《如何在CDH中使用Phoenix》中介绍了Cloudera Labs中的Phoenix,以及如何在CDH5.11.2中安装和使用Phoenix4.7。本文Fayson主要介绍如何在CDH中使用Phoenix在HBase上建立二级索引。

  • 内容概述:

1.建表与数据准备

2.启用Kafka的Sentry赋权

3.Kafka的赋权测试

4.总结

  • 测试环境:

1.CM5.14.3/CDH5.14.2

2.Phoenix4.7.0

3.操作系统版本为Redhat7.4

4.采用root用户进行操作

5.集群未启用Kerberos

2.建表与数据准备


1.首先确保你的CDH集群已经安装Phoenix的Parcel,安装过程省略,具体可以参考《如何在CDH中使用Phoenix》。

2.准备一个测试csv文件用来导入Phoenix的表中,Fayson这里准备一个1.2GB,995W行,11个字段的数据文件。

[root@ip-172-31-6-83 generatedata]# cat hbase_data.csv | wc -l
9950000
[root@ip-172-31-6-83 generatedata]# du -sh hbase_data.csv
1.2G    hbase_data.csv
[root@ip-172-31-6-83 generatedata]# head hbase_data.csv
340111200507061443,鱼言思,0,遂宁,国家机关,13004386766,15900042793,广州银行1,市场三街65号-10-8,0,1
320404198104281395,暨梅爱,1,临沧,服务性工作人员,13707243562,15004903315,广州银行1,太平角六街145号-9-5,0,3
371326195008072277,人才奇,1,黔西南,办事人员和有关人员,13005470170,13401784500,广州银行1,金湖大厦137号-5-5,1,0
621227199610189727,谷岚,0,文山,党群组织,13908308771,13205463874,广州银行1,仰口街21号-6-2,1,3
533324200712132678,聂健飞,1,辽阳,不便分类的其他劳动者,15707542939,15304228690,广州银行1,郭口东街93号-9-3,0,2
632622196202166031,梁子伯,1,宝鸡,国家机关,13404591160,13503123724,广州银行1,逍遥一街35号-14-8,1,4
440883197110032846,黎泽庆,0,宝鸡,服务性工作人员,13802303663,13304292508,广州银行1,南平广场113号-7-8,1,4
341500196506180162,暨芸贞,0,黔西南,办事人员和有关人员,13607672019,13200965831,广州银行1,莱芜二路117号-18-3,1,4
511524198907202926,滕眉,0,南阳,国家机关,15100215934,13406201558,广州银行1,江西支街52号-10-1,0,3
420205198201217829,陶秀,0,泸州,商业工作人员,13904973527,15602017043,广州银行1,城武支大厦126号-18-2,1,0

(可左右滑动)

3.连接到Phoenix的终端,在Phoenix中建表hbase_test

cd /opt/cloudera/parcels/CLABS_PHOENIX/bin

./phoenix-sqlline.py ip-172-31-6-83.ap-southeast-1.compute.internal:2181:/hbase create table hbase_test
(
s1 varchar not null primary key,
s2 varchar,
s3 varchar,
s4 varchar,
s5 varchar,
s6 varchar,
s7 varchar,
s8 varchar,
s9 varchar,
s10 varchar,
s11 varchar
);

(可左右滑动)

4.将准备好的csv文件put到HDFS,然后通过Phoenix自带的bulkload工具将准备好的csv文件批量导入到Phoenix的表中。

[root@ip-172-31-6-83 generatedata]# hadoop fs -mkdir /fayson 
[root@ip-172-31-6-83 generatedata]# hadoop fs -put hbase_data.csv /fayson
[root@ip-172-31-6-83 generatedata]#

(可左右滑动)

[root@ip-172-31-6-83 generatedata]# HADOOP_CLASSPATH=/opt/cloudera/parcels/CDH/lib/hbase/hbase-protocol-1.2.0-cdh5.7.6.jar:/opt/cloudera/parcels/CDH/lib/hbase/conf hadoop jar /opt/cloudera/parcels/CLABS_PHOENIX/lib/phoenix/phoenix-4.7.0-clabs-phoenix1.3.0-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -t hbase_test -i /fayson/hbase_data.csv

(可左右滑动)

5.在Phoenix和hbase shell中分别查询确认数据入库成功。

select * from HBASE_TEST limit 10;

scan 'HBASE_TEST',{LIMIT => 1}

(可左右滑动)

3.Covered Indexes(覆盖索引)


1.使用覆盖索引获取数据的过程中,内部不需要再去HBase的原表获取数据,查询需要返回的列都会被存储在索引中。要想达到这种效果,你的select的列,where的列都需要在索引中出现。举个例子,如果你的SQL语句是select s2 from hbase_test where s6='13505503576',要最大化查询效率和速度最快,可以建立覆盖索引。

CREATE INDEX index1_hbase_test ON hbase_test(s6) INCLUDE(s2)

(可左右滑动)

提示要对HBase进行一些配置才能执行该语句。

2.将以下配置增加到hbase-site.xml,通过Cloudera Manager搜索HBase服务的“hbase-site.xml 的 HBase 服务高级配置代码段(安全阀)”。

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

(可左右滑动)

保存更改,然后重启HBase。

3.在执行建立覆盖索引之前,我们先执行2个查询语句方便后面跟建立索引后的查询时间进行对比。

select s6 from hbase_test where s6='13505503576';
select s2 from hbase_test where s6='13505503576';

(可左右滑动)

4.再次执行建立覆盖索引的语句

CREATE INDEX index1_hbase_test ON hbase_test(s6) INCLUDE(s2);

(可左右滑动)

5.再次执行上面2个查询语句。

select s6 from hbase_test where s6='13505503576';
select s2 from hbase_test where s6='13505503576';

(可左右滑动)

发现都是毫秒级返回,而之前2个查询都是需要30几秒。

6.我们再来具体看看建立覆盖索引的语句。

CREATE INDEX index1_hbase_test ON hbase_test(s6) INCLUDE(s2);

(可左右滑动)

果查询项中不包含除s2和s6之外的列,而且查询条件不包含除s2之外的列,则可以确保该查询使用Index,关键字INCLUDE包含需要返回数据结果的列。这种索引方式的最大好处就是速度快,而我们也知道,索引就是空间换时间,所以缺点也很明显,存储空间耗费较多。

如上图所示,Phoenix的索引其实就是建了一张HBase的表。你可以通过hbase shell的list命令看到。查看表index1_hbase_test,你会发现,这张表一共三列,一列就是索引,第二列是RowKey,最后一列就是s2的值。很明显在这里记录的RowKey,就是为了快速查找HBase中的数据。只是这里用不到,s2已经被保存到了这张索引表中,直接返回。

4.Functional Indexes(函数索引)


函数索引从从Phoenix4.3版本就有,这种索引的内容不局限于列,还能在表达式上建立索引。如果你使用的表达式正好就是索引的话,数据也可以直接从这个索引获取,而不需要从数据库获取。

1.在建立函数索引时,我们先执行两个查询语句好方便与建立索引以后的性能进行对比。

select s1,s7 from hbase_test where substr(s7,1,10)='1550864580';

select s1,substr(s7,1,10) from hbase_test where substr(s7,1,10)='1550864580';

(可左右滑动)

2.建立函数索引

create index index2_hbase_test on hbase_test (substr(s7,1,10));

(可左右滑动)

3.再次执行前面的查询语句进行比较

select s1,s7 from hbase_test where substr(s7,1,10)='1550864580';

select s1,substr(s7,1,10) from hbase_test where substr(s7,1,10)='1550864580';

(可左右滑动)

如果查询项包含substr(s7,1,10),则查询时间在毫秒级,而之前需要30多秒。如果查询项不包含substr(s7,1,10),则跟不建索引时是一样的。如果想让第一个查询语句走索引,我们可以在建立索引时采用INCLUDE(S7)来实现。

5.Global Indexes(全局索引)


全局索引适合那些读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)。而查询数据的时候,Phoenix会通过索引表来快速低损耗的获取数据。默认情况下,如果你的查询语句中没有索引相关的列的时候,Phoenix不会使用索引。

6.Local Indexes(本地索引)


本地索引适合那些写多读少,或者存储空间有限的场景。和全局索引一样,Phoenix也会在查询的时候自动选择是否使用本地索引。本地索引之所以是本地,只要是因为索引数据和真实数据存储在同一台机器上,这样做主要是为了避免网络数据传输的开销。如果你的查询条件没有完全覆盖索引列,本地索引还是可以生效。因为无法提前确定数据在哪个Region上,所以在读数据的时候,还需要检查每个Region上的数据而带来一些性能损耗。

1.先删除之前建立的函数索引INDEX2_HBASE_TEST。

drop index INDEX2_HBASE_TEST on hbase_test;

(可左右滑动)

2.建立本地索引

create local index index2_hbase_test on hbase_test (s7);

(可左右滑动)

3.在查询项中不包含索引字段的条件下,一样查询比较快速。

select s2 from hbase_test where s7='13500591348';
select * from hbase_test where s7='13500591348';

(可左右滑动)

可以发现这2个查询语句返回时间都在毫秒级,而如果不建立索引,查询时间为35S以上。

7.总结


Phoenix的二级索引主要有两种,即全局索引和本地索引。全局索引适合那些读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。本地索引适合那些写多读少,或者存储空间有限的场景。

索引定义完之后,一般来说,Phoenix会判定使用哪个索引更加有效。但是,全局索引必须是查询语句中所有列都包含在全局索引中,它才会生效。举个例子,下面是创建索引的语句:

create index my_index on hbase_test (s6);

(可左右滑动)

而查询语句是

select s2 from hbase_test where s6='13505503576';

(可左右滑动)

上例就不会用到索引my_index。因为s2并没有包含在索引中。所以使用全局索引,必须要所有的列都包含在索引中。那么怎样才能使用索引呢?有三种方法。

1.创建索引时使用覆盖索引

CREATE INDEX index1_hbase_test ON hbase_test(s6) INCLUDE(s2)

(可左右滑动)

这种索引会把s2加到索引表里面,同时s2也会随着原数据表中的变化而变化。这种方式很明显的缺点是索引表的大小较大,然后就是全局索引不适合写特别多的情况。

这个查询效果具体可以参考第三章

2.使用类似于Oracle的Hint,强制索引。

select  /*+ INDEX(hbase_test index1_hbase_test)*/ s5 from hbase_test where s6='13505503576';

(可左右滑动)

如果不带hint,查询时间为35s,带了hint强制使用索引后查询时间为0.099秒。

查询引擎会使用index1_hbase_test这个索引,由于它会发现索引表中没有s5数据,所以每一行它都会去原数据表中获取s5的值。这个强制索引只有在你认为索引有比较好的选择性的时候才是好的选择,也就是说s6等于13505503576的行数不多。不然的话,使用Phoenix默认的全表扫描的性能也许会更好。

3.创建本地索引

create local index index2_hbase_test on hbase_test (s7);

(可左右滑动)

本地索引和全局索引不同的是,查询语句中,即使所有的列都不在索引定义中,它也会使用索引,这是本地索引的默认行为。Phoenix知道原数据和索引数据在同一个RegionServer上,能保证索引查找是本地的。本地索引查询效果具体可参见第6章。

注:使用函数索引,查询语句中带上hint也没有作用。

参考:

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

https://www.cnblogs.com/haoxinyue/p/6724365.html

https://blog.csdn.net/u011491148/article/details/45749807

https://www.cnblogs.com/MOBIN/p/5467284.html

提示:代码块部分可以左右滑动查看噢

为天地立心,为生民立命,为往圣继绝学,为万世开太平。 温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。

推荐关注Hadoop实操,第一时间,分享更多Hadoop干货,欢迎转发和分享。

原创文章,欢迎转载,转载请注明:转载自微信公众号Hadoop实操

原文发布于微信公众号 - Hadoop实操(gh_c4c535955d0f)

原文发表时间:2018-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java后端技术栈

在一个千万级的数据库查寻中,如何提高查询效率?

A. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

1073
来自专栏后端技术探索

mysql 水平分表的几种方法

当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。

1.2K2
来自专栏北京马哥教育

MySQL 5.7原生JSON格式支持

在MySQL与PostgreSQL的对比中,PG的JSON格式支持优势总是不断被拿来比较。其实早先MariaDB也有对非结构化的数据进行存 储的方案,称为dyn...

3226
来自专栏漫漫全栈路

Oracle数据库项目——MC服务器管理系统

数据库设计内容,分为:系统功能说明,数据库分析与设计,数据库实现。本数据库系统提供的功能用于项目MC-Servers-Web,详情内容参见MC-Service...

7054
来自专栏扎心了老铁

Elasticsearch-sql 用SQL查询Elasticsearch

Elasticsearch的查询语言(DSL)真是不好写,偏偏查询的功能千奇百怪,filter/query/match/agg/geo各种各样,不管你是通过封装...

1.1K4
来自专栏杨建荣的学习笔记

MySQL中使用pt-osc的一些小结

Percona的pt-osc工具算是DBA的一个福利工具。想想一个数据量有些大的表,在上面做DDL操作真是一种煎熬,我们也基本理解了这是一种空间换时间的...

1351
来自专栏aoho求索

MySQL探秘(五):InnoDB锁的类型和状态查询

 锁是数据库系统区分于文件系统的一个关键特性。数据库使用锁来支持对共享资源进行并发访问,提供数据的完整性和一致性。此外,数据库事务的隔离性也是通过锁实现的。In...

1061
来自专栏跟着阿笨一起玩NET

SQL语句使用总结(一)

1>. FROM 2>. WHERE 3>. GROUP BY 4>. HAVING 5>. SELECT 6>. ORDER BY

501
来自专栏idba

insert 语句加锁机制

之前的文章里面总结了很多死锁案例,其实里面有几篇文章对于insert加锁流程表述的不准确,而且微信公众号又无法修改,所以通过本文重新梳理insert...

1243
来自专栏数据和云

循序渐进:Oracle 12c新特性Sharding技术解读

引言 数据库构架设计中主要有 Shared Everthting、Shared Nothing 和 Shared Disk: Shared Everthting...

4567

扫码关注云+社区

领取腾讯云代金券