本文作者:林伟兵,叩丁狼高级讲师。原创文章,转载请注明出处。
3.5.使用DBeaver客户端
Phoenix常见的客户端连接工具有SQuirrel和DBeaver,这里主要介绍DBeaver客户端的使用方式。
安装DBeaver,启动DBeaver,将 phoenix-[version]-client.jar 拷贝到客户端。
注意:客户端如何缺失某些参数配置,可以上面第4步的驱动属性添加再测试连接,这是因为DBeaver不支持hbase-site.xml配置文件的使用.
3.6.Phoenix二级索引
前一章介绍了Phoenix简单的DDL和CURD操作,接下来这一节主要介绍Phoenix独有的特性[二级索引](http://phoenix.apache.org/secondary_indexing.html),并在DBeaver中实践。
对HBase来说,我们通常使用字典序的RowKey来快速访问数据,除此之外也可使用自定义的Filter来搜索数据,但是它是基于全表扫描的。而Phoenix提供的二级索引是避开了全表扫描,其利用空间换时间的来解决查询过程中的缓慢问题;默认情况下客户端不支持二级索引,需要将以下配置添加到HBase的各个RegionServer节点的hbase-site.xml文件中:
<property>
<name>hbase.regionserver.wal.codec</name>
<value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
覆盖索引 Covered Indexes
Phoenix提供了一种叫Covered Index的二级索引。这种索引在获取数据的过程中,内部不需再去HBase原表中获取任何数据,转而在索引表查询结果即可。
要想达到这种效果,你的select 的列,where 的列都需要在索引表中出现。举个例子,如果你的SQL语句是SELECT name FROM WOLFCODE_MDB.t_employee ORDER BY SALARY DESC;
,要达到最大化查询效率和速度最快,你就需要建立覆盖索引:
CREATE INDEX salary_idx ON wolfcode_mdb.t_employee(salary DESC) INCLUDE (name);
## 原表的内容是:
+-----+-----------+----------+---------+
| ID | NAME | SALARY | GENDER |
+-----+-----------+----------+---------+
| 1 | zhangsan | 10800.0 | M |
| 2 | lisi | 9900.0 | M |
| 3 | wangwu | 7500.0 | F |
| 4 | zhaoliu | 10000.0 | M |
+-----+-----------+----------+---------+
## 索引表建立后内容是:
+-----------+------+-----------+
| 0:SALARY | :ID | 0:NAME |
+-----------+------+-----------+
| 1.08E+4 | 1 | zhangsan |
| 1E+4 | 4 | zhaoliu |
| 9.9E+3 | 2 | lisi |
| 7.5E+3 | 3 | wangwu |
+-----------+------+-----------+
## 当执行如下SQL时,系统会找到对应的二级索引表进行查询,二级索引表的表内容明显比原表的内容少,并且在查询的过程无需再次排序,这也大大减少了查询的时间。
## 但是索引表的建立无疑也降低了集群的存储能力。
SELECT name FROM WOLFCODE_MDB.t_employee ORDER BY SALARY DESC;
覆盖索引就是一种典型的全局索引,全局索引适合那些读多写少的场景。使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表。而查询数据的时候,Phoenix会通过索引表来快速低损耗的获取数据。
如下当在原表插入数据后,索引表也会插入对应的数据:
UPSERT INTO t_employee VALUES(5,'亦舒',8800,'F');
+-----------+------+-----------+
| 0:SALARY | :ID | 0:NAME |
+-----------+------+-----------+
| 1.08E+4 | 1 | zhangsan |
| 1E+4 | 4 | zhaoliu |
| 9.9E+3 | 2 | lisi |
| 8.8E+3 | 5 | 亦舒 |
| 7.5E+3 | 3 | wangwu |
+-----------+------+-----------+
如果某个查询已不在频繁,建议删除索引表以换取更多的空间,代码如下:
use wolfcode_mdb;
DROP INDEX SALARY_IDX ON wolfcode_mdb.t_employee;
函数索引 Functional Indexes
函数索引从4.3版本就有,这种索引的内容不局限于列,还能在表达式上建立索引。如果你使用的表达式正好就是索引的话,数据也可以直接从这个索引获取,而不需要从数据库获取。比如说,在一个表达式上建立索引,这个表达式是salary * 12
,值得注意的是,函数索引不支持排序:
CREATE INDEX SALARY_PER_YEAR_IDEX2 ON t_employee(salary * 12);
SELECT * FROM wolfcode_mdb.SALARY_PER_YEAR_IDEX2;
## 查询结果如下
+-----------------+------+
| :(SALARY * 12) | :ID |
+-----------------+------+
| 9E+4 | 3 |
| 1.056E+5 | 5 |
| 1.188E+5 | 2 |
| 1.2E+5 | 4 |
| 1.296E+5 | 1 |
+-----------------+------+
本地索引 Local Indexes
本地索引适合那些写多读少或存储空间有限的场景。和全局索引一样,Phoenix也会在查询的时候自动选择是否使用本地索引。本地索引之所以是本地,主要是因为索引数据和真实数据存储在同一台机器上,这样做主要是为了避免网络数据传输的开销。
异步创建索引
注意:https://yq.aliyun.com/ask/438584/
注意:http://hbase.group/question/27
一般我们可以使用CREATE INDEX来创建一个索引,这是一种同步的方法。但是有时候我们创建索引的表非常大,我们需要等很长时间。Phoenix 4.5以后有一个异步创建索引的方式,使用关键字ASYNC来创建索引:
CREATE INDEX my_index ON t_employee(salary desc) async;
SELECT * FROM my_index;
这时候创建的索引表中不会有数据。你还必须要单独的使用命令行工具来执行数据的创建。当语句给执行的时候,后端会启动一个map reduce任务,只有等到这个任务结束,数据都被生成在索引表中后,这个索引才能被使用。启动工具的方法:
${HBASE_HOME}/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool \
--schema wolfcode_mdb --data-table t_employee --index-table my_index \
--output-path /async_idx_hfiles
这个任务不会因为客户端给关闭而结束,是在后台运行。你可以在指定的文件ASYNC_IDX_HFILES中找到最终实行的结果。
3.7.JDBC API的实现
-
添加依赖。
<dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-core</artifactId> <version>4.14.1-HBase-1.2