HDFS随机读取效率较低,HBASE是BigTable的开源版本,是建立在HDFS上,提供高可靠性、高性能、列存储、可伸缩、实时读写NoSQL的数据库系统。仅支持单行事务,存储结构化和半结构化数据,不支持join。面向列且稀疏。
1、应用场景
- 对象存储
- 时序数据:HBase之上有OpenTSDB模块,满足时序场景
- 用户画像:较大的稀疏矩阵
- 时空数据:轨迹、气象等数据
- 消息、订单
2、特点
- 强一致性读写
- 自动分块:通过Region分布在集群上,随数据增长进行自动拆分和分布
- 块缓存和布隆过滤器
3、HBASE安装、启动、停止
版本选择
hadoop与hbase版本对应网址:https://hbase.apache.org/book.html#basic.prerequisites
下载安装包
下载地址:https://archive.apache.org/dist/hbase/
解压
tar -zxvf hbase-2.4.0-bin.tar.gz -C /export/soft/hbase
修改hbase配置文件
cd /export/soft/hbase/hbase-2.4.0/conf
vim hbase-env.sh
vim hbase-site.xml
在hbase-env.sh增加如下:
export JAVA_HOME=/usr/lib/jvm/java
export HBASE_MANAGES_ZK=false
hbase-site.xml 修改如下:
<configuration>
<!-- 设置hbase集群为分布式集群 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 此目录regionserver共享的目录,用来持久存储HBase的数据,其默认值为:${hbase.tmp.dir}/hbase,如果不修改默认值,数据将会在集群重启时丢失。 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop100:8020/hbase</value>
</property>
<!-- 设置zookeeper集群,用英文逗号分隔 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop100:2181,hadoop101:2181,hadoop102:2181</value>
</property>
<!-- hbase备份的副本数,不能超过datanode的节点数。
hbase的数据备份数需要再hbase-site.xml配置文件中单独设置,否则hbase写入的数据regionServer只会保存一份! -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>hbase.tmp.dir</name>
<value>./tmp</value>
</property>
<!-- 解决启动HMaster无法初始化WAL的问题 -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
<!-- Zookeeper元数据的存储目录,需要和Zookeeper的zoo.cfg 配置的一致 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/soft/zookeeper/apache-zookeeper-3.5.7-bin/zkData</value>
</property>
</configuration>
修改regionservers
vim regionservers
将regionservers修改为各个节点名称
hadoop100
hadoop101
hadoop102
修改系统配置文件(集群所有机器都改)
vim /etc/profile
增加配置如下:
export HBASE_HOME=/export/soft/hbase/hbase-2.4.0
export PATH=$PATH:$HBASE_HOME/bin
执行source命令
source /etc/profile
将hbase文件夹传到其他机器上
scp -r /export/soft/hbase hadoop101:$PWD
scp -r /export/soft/hbase hadoop102:$PWD
启动
start-hbase.sh
如下图:
启动出现Error: JAVA_HOME is not set:hbase-env.sh配置没识别到java路径**
停止
stop-hbase.sh
如果停止不了.
方法1:输入
/export/soft/hbase/hbase-2.3.5/bin/hbase-daemons.sh stop regionserver
/export/soft/hbase/hbase-2.3.5/bin/hbase-daemons.sh stop master
/export/soft/hbase/hbase-2.3.5/bin/stop-hbase.sh
方法2:使用jps命令后,用kill-9杀掉H开头的进程
查看webUI界面
网址:http://192.168.132.100:16010/
进入hbase的shell,如果环境变量没生效,在hbase的bin文件夹下
hbase shell
如果报错org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet的解决方案:https://blog.youkuaiyun.com/Dan1374219106/article/details/112981875
4、HBase数据模型
4.1、存储结构
HBASE中数据存储在行和列的表中,但把数据看成多维度的Map更合适。
4.2、术语
HBase数据以表的形式组织,表由多个行组成。
HBase中的行由一个RowKey和多列组成,行在存储时行键按顺序排序。设计时,尽量让相关的行存储在一起。
HBase中的列由列族(Column Family)和列限定符组成(Column Qualifier)组成。如:C1:USER_ID。列族中不会存储任何内容。一个列族里的数据在HDFS中存储在一块,列族越少越好,最多不超过两个。
官方建议:列族中的列数保持一样。
单元格:是行、列族和列限定符的组合。包含一个值和一个时间戳。内容以二进制存储。
ROW | COLUMN+CELL |
---|---|
0001 | column=C1:Name,timestamp=…,value=\xC9\xBD\ |
0001 | column=C1:Age,timestamp=…,value=20 |
0001 | column=C1:Date,timestamp=…,value=2019-02-02 |
0001 | column=C1:Money,timestamp=…,value=112 |
5、shell操作
list查看所有表,status查看hbase状态。
创建表
create "ORDER_INFO","C1"
禁用表
disable "ORDER_INFO"
删除表
drop "ORDER_INFO"
插入数据
put "ORDER_INFO","00001","C1:STATUS","已提交"
put "ORDER_INFO","00001","C1:STATUS","已提交"
查找数据
get "ORDER_INFO" ,"00001"
数据转中文
get "ORDER_INFO" ,"00001",{FORMATTER => 'toString'}
更改数据
put "ORDER_INFO","00001","C1:STATUS","未提交"
删除指定列
delete "ORDER_INFO","00001","C1:MONEY"
删除整条数据
deleteall "ORDER_INFO","00001"
计数
1、制作数据
put "TEST","100001","C1:TEST_COLUMN","0.232183643524708"
put "TEST","100002","C1:TEST_COLUMN","0.480198634708151"
put "TEST","100003","C1:TEST_COLUMN","0.128342178232338"
put "TEST","100004","C1:TEST_COLUMN","0.650995466796528"
put "TEST","100005","C1:TEST_COLUMN","0.258112808949395"
put "TEST","100006","C1:TEST_COLUMN","0.654182165869505"
put "TEST","100007","C1:TEST_COLUMN","0.300093884317414"
put "TEST","100008","C1:TEST_COLUMN","0.699595007176494"
put "TEST","100009","C1:TEST_COLUMN","0.80626233289207"
put "TEST","100010","C1:TEST_COLUMN","0.234573285604112"
put "TEST","100011","C1:TEST_COLUMN","0.566811410616281"
put "TEST","100012","C1:TEST_COLUMN","0.36149246469257"
put "TEST","100013","C1:TEST_COLUMN","0.159009233791409"
put "TEST","100014","C1:TEST_COLUMN","0.0470956363017861"
put "TEST","100015","C1:TEST_COLUMN","0.448075364748759"
put "TEST","100016","C1:TEST_COLUMN","0.172706803478583"
put "TEST","100017","C1:TEST_COLUMN","0.529336545518016"
put "TEST","100018","C1:TEST_COLUMN","0.633312289477801"
put "TEST","100019","C1:TEST_COLUMN","0.194791765001028"
put "TEST","100020","C1:TEST_COLUMN","0.448071045980456"
put "TEST","100021","C1:TEST_COLUMN","0.581239019375673"
put "TEST","100022","C1:TEST_COLUMN","0.116903596186785"
2、插入数据
hbase shell /export/test.txt
3、计数(大数据量慎用,会很卡)
count "TEST"
数据量大使用MR程序来计数
扫描
1、扫描整表(慎重!)
scan "TEST"
2、只扫描3条
scan 'TEST',{LIMIT=>3}
3、扫描某列
scan 'TEST',{LIMIT=>3,COLUMNS=>['C1:TEST_COLUMN']}
4、扫描多列
scan 'TEST',{LIMIT=>3,COLUMNS=>['C1:TEST_COLUMN','C1:XXXX','C1:XXXX']}
5、按rowkey和列名扫描
scan 'TEST',{LIMIT=>3,COLUMNS=>['C1:TEST_COLUMN'],ROWPREFIXFILTER=>'100010'}
6、过滤器
按照rowkey进行过滤
scan 'TEST',{FILTER=>"RowFilter(=,'binary:100010')"}
按照列进行过滤
scan 'TEST',{FILTER=>"SingleColumnValueFilter('C1','TEST_COLUMN',=,'binary:0.234573285604112')"}
组合条件过滤
scan 'TEST',{FILTER=>"RowFilter(=,'binary:100010') AND SingleColumnValueFilter('C1','TEST_COLUMN',=,'binary:0.234573285604112')"}
注意:过滤器比较为字符比较,不是数值比较
7、INCR
可实现对某个单元格的值进行原子性计数。语法如下:
incr ‘表名’,‘rowkey’,‘列族:列名’,累加值(默认加1)
使用get_couter获取计数器的操作,get获取不到
8、shell管理操作
创建命名空间
hbase:002:0> create_namespace "TEST"
Took 0.1953 seconds
查看命名空间
hbase:004:0> list_namespace
NAMESPACE
TEST
default
hbase
3 row(s)
Took 0.2979 seconds
hbase:005:0>
删除命名空间
hbase:005:0> drop_namespace "TEST"
Took 0.1942 seconds
状态status
hbase:001:0> status
1 active master, 0 backup masters, 3 servers, 0 dead, 1.3333 average load
Took 0.7875 seconds
查看用户
hbase:002:0> whoami
root (auth:SIMPLE)
groups: root
Took 0.0259 seconds
查看所有表
hbase:003:0> list
TABLE
ORDER_INFO
TEST
2 row(s)
Took 0.0345 seconds
=> ["ORDER_INFO", "TEST"]
展示表结构信息
hbase:004:0> describe 'TEST'
Table TEST is ENABLED
TEST
COLUMN FAMILIES DESCRIPTION
{NAME => 'C1', BLOOMFILTER => 'ROW', IN_MEMORY => 'false', VERSIONS => '1', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', COMPRESSION => 'NONE', TTL => 'FOREVER', MIN
_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
1 row(s)
Quota is disabled
Took 0.1851 seconds
判断是否存在
hbase:006:0> exists 'TEST'
Table TEST does exist
Took 0.0177 seconds
=> true
判断是否禁用
hbase:007:0> is_disabled 'TEST'
false
Took 0.0108 seconds
=> false
hbase:008:0> is_enabled 'TEST'
true
Took 0.0175 seconds
=> true
增加列族
hbase:009:0> alter 'TEST','C2'
Updating all regions with the new schema...
1/1 regions updated.
Done.
Took 1.9698 seconds
删除列族(慎用,删库跑路用)
hbase:010:0> alter 'TEST','delete'=>'C2'
Updating all regions with the new schema...
1/1 regions updated.
Done.
Took 1.7860 seconds
禁用表
hbase:010:0> alter 'TEST','delete'=>'C2'
Updating all regions with the new schema...
1/1 regions updated.
Done.
Took 1.7860 seconds
启用表
hbase:010:0> alter 'TEST','delete'=>'C2'
Updating all regions with the new schema...
1/1 regions updated.
Done.
Took 1.7860 seconds
删除表drop
清空表truncate (内部流程:禁用-删除-创建)
9、Java操作HBase
hbase的hbase-site.xml、core-site.xml拷贝到idea的resource文件夹,对resource文件夹进行rebuild ‘‘
maven
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.4.0</version>
</dependency>
初始化
@Before
public void beforeTest() throws IOException {
Configuration configuration = HBaseConfiguration.create();
connection = ConnectionFactory.createConnection(configuration);
admin = connection.getAdmin();
}
关流
@After
public void afterTest() throws IOException {
admin.close();
connection.close();
}
建表
流程:
- 建立HBase连接
- 创建Admin对象
- exists判断表是否存在
- 创建表需要构建tableDescriptor(表描述器)、columnFamilyDescriptor(列族描述器)
- 将columnFamilyDescriptor添加到tableDescriptor中
- 使用admin创建表
public void createTableTest() throws IOException {
TableName tableName = TableName.valueOf("stock_price2");
//先判断表是否存在
if(admin.tableExists(tableName)){return;}
//表建造者
TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tableName);
//列族建造者
ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("C1"));
//列族描述器
ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();
//列族和表关联
tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
//表描述器
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
admin.createTable(tableDescriptor);
System.out.println("创建表成功");
}
删表
@Test
public void deleteTable() throws Exception {
TableName tableName = TableName.valueOf("stock_price1");
if (admin.tableExists(tableName)){
admin.disableTable(tableName);
admin.deleteTable(tableName);
}
}
插入数据
@Test
public void putTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("TEST"));
String rowKey="110000";
String columnFamily="C1";
String columnName = "TEST_COLUMN";
Put put = new Put(Bytes.toBytes(rowKey));
put.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(columnName),Bytes.toBytes(321321));
table.put(put);
table.close();
}
查询数据
@Test
public void getTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("TEST"));
String rowKey="110000";
String columnFamily="C1";
String columnName = "TEST_COLUMN";
Result result = table.get(new Get(Bytes.toBytes(rowKey)));
System.out.println(result);
byte[] value = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName));
System.out.println(Bytes.toInt(value));
table.close();
}
删除数据
@Test
public void deleteTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("TEST"));
String rowKey="110000";
String columnFamily="C1";
String columnName = "TEST_COLUMN";
table.delete(new Delete(Bytes.toBytes(rowKey)));
table.close();
}
扫描表
@Test
public void testScan() throws IOException {
String rowKey="110000";
String columnFamily="C1";
String columnName = "TEST_COLUMN";
Table table = connection.getTable(TableName.valueOf("TEST"));
Scan scan = new Scan();
SingleColumnValueFilter end = new SingleColumnValueFilter(Bytes.toBytes(columnFamily), Bytes.toBytes(columnFamily), CompareOperator.LESS_OR_EQUAL, Bytes.toBytes(0.9));
SingleColumnValueFilter start = new SingleColumnValueFilter(Bytes.toBytes(columnFamily), Bytes.toBytes(columnFamily), CompareOperator.GREATER_OR_EQUAL, Bytes.toBytes(0.5));
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, start, end);
scan.setFilter(filterList);
ResultScanner results = table.getScanner(scan);
while (results.iterator().hasNext()) {
System.out.println(results.next());
}
table.close();
}
10、HBase高可用
高可用通过ZK的临时节点和监听机制实现。
在hbase的conf文件夹创建backup-masters文件,里面添加hadoop101,hadoop102
vim backup-masters
重启hbase后在webUI界面可看待Backup Masters
11、HBase架构
11.1、系统架构
与hadoop 集群对比
master Server:
- 监控Region Server并处理故障转移
- 处理元数据变更
- region分配和移除
- 负载均衡:通过读取meta元数据了解Region分配,通过ZK了解Region Server启动情况,5min调控一次平衡
- 通过ZK发布自己位置给客户端
Region Server:
- 处理分配给它的Region
- 存储HBase数据
- 刷新缓存到HDFS
- 维护HLog
- 执行压缩
- 处理分片
Region Server包含组件:
- Write-Ahead logs
- HFile
- Store
- MemStore
- Region
11.2、逻辑架构
Region Server结构
HBase中表被划分为很多Region,有Region Server提供服务。Region按列族垂直划分为Store存在HDFS中,即一个列族就是一个Store。
横向扩展:生成多个Region
纵向扩展:生成多个列族(Store)
MemStore:给列族增加一层缓存,一个store文件对应一个MemStore缓存
StoreFile(HFIle):HBase存在HDFS上的数据文件
WAL(Write-Ahead logs):HBase中一种高并发、持久化的日志保存和回放机制,用来故障恢复。CRUD操作会保存到WAL中。一旦服务器宕机可通过回放WAL可实现故障恢复,物理文件为Sequence FIle存在HDFS上。
11.3、HBase写流程
- client向ZK发送请求创建连接
- 读取ZK存储meta表是由哪个Region Server管理
- 读取meta表,作为属性保存到连接中
- 发送put,如果meta表变化则重复步骤1、2、3
- 将请求写入WAL并落盘
- 操作put请求,写入对应的MemStore并排序
- 等待触发刷写条件写入对应的store
11.4、MemStore刷写
刷写由多个线程控制,条件相互独立:
- MemStore大小达到128M(默认,根据HDFS块大小来定),其所在Region的所有MemStore都会刷写,列族过多,有的MemStore没达到128M,会产生很多小文件影响性能。
- Region Server中的FlushHandler控制高低位避免写缓存过多导致OOM
- 为避免数据长时间存在内存中也会触发刷写机制,5min监控一次,1h刷写一次。
11.5、HBase读流程
- client向ZK发送请求创建连接
- 读取ZK存储meta表是由哪个Region Server管理
- 读取meta表,作为属性保存到连接中
- 发送get,如果meta表变化则重复步骤1、2、3
- 将请求写入WAL并落盘
- 读取Block Cache、MemStore缓存并缓存到Block Cache、读取store文件
- 合并所有数据并返回
11.6、HFile结构
HFile是存储在HDFS上每个store文件夹下实际数据文件,包括数据键值对(key-value,默认64K)、元数据、文件信息、数据索引、元数据索引等。HFile经过序列化无法直接查看。
11.7、文件合并
MemStore每次刷写都会生成新HFile,文件太多时会进行文件合并,同时清理掉过期和删除的数据。
小合并:将邻近的若干较小的HFile合并成一个较大的HFile,同时清理掉过期和删除的数据。
大合并:将Store下所有的HFile合并成一个大HFile,并会清理掉过期和删除的数据,默认7天。
小合并时:只合并周围的数据,同时删除也只能删周围的数据
大合并时:会把之前的所有数据全部删除
小合并最小文件数3,最大文件数10,单个HFile最小值128M,小于128M的文件一定会被合并。
12、Rowkey设计
设计原则:
- 避免使用递增行键和时序数据。数据写入时会导致负载都在一台机器上。
- 避免rowkey和列长度过大。
- 数字使用long等类型比string类型更省空间
避免热点设计,防止rowkey过于集中,导致负载不均衡。方法:
- 反转:将rowkey后几位经常变换的放到前面
- 前面加随机数,但查询麻烦
- 对rowkey的全部或部分进行hash,但会产生哈希碰撞
13、预分区
为防止单台机器负载过大,使用预分区来保证负载均衡。虽然HBase在数据量大时Region会自己进行分裂形成多分区,但预分区使得存储效率有所提升,不会等到自动分区,但对Scan的性能有一定牺牲。
预分区个数=节点倍数。Region默认大小10G。
两种策略:
-
根据startkey和endkey划分
hbase:013:0> create "TEST2",{NAME=>"C1",COMPRESSION=>"GZ"},{SPLITS=>['1000','2000','3000']} Created table TEST2 Took 1.1472 seconds => Hbase::Table - TEST2
-
直接指定数量和key的算法,startkey和endkey由HBase自动生成
hbase:008:0> create "TEST1",{NAME=>"C1",COMPRESSION=>"GZ"},{NUMREGIONS=>6,SPLITALGO=>"HexStringSplit"}
Created table TEST1
Took 1.2717 seconds
=> Hbase::Table - TEST1
14、Phoenix
官网:https://phoenix.apache.org/
解决问题:
- HBase不能使用SQL语言
- HBase没有二级索引
14.1、简介
Phoenix让Hadoop支持OLTP和业务操作分析。可提供标准的SQL以及完备的ACID事务支持。Phoenix通过协处理器在服务端执行操作。
Phoenix是基于HBase进行的扩展,核心是一些Phoenix开头的jar包,这些jar包实现了很多协处理器(执行put/get/delete这些操作的时候可以执行一段特殊代码)
14.2、安装Phoenix
Phoenix这破玩意我按了一天,都是坑!从早上10点搞到晚上11:46,吐了。。。。
都把原来的2.4.0的HBase卸载了,重新装的2.4.11,其实跟那都没关系。。。。。
先把HBase集群停止。
-
下载并解压
下载网址:https://phoenix.apache.org/download.html。根据自己HBase版本就行选型。
-
配置环境变量
# For Phoenix export PHOENIX_HOME=/export/soft/phoenix-hbase-2.4-5.1.3-bin export PHOENIX_CLASSPATH=$PHOENIX_HOME export PATH=$PHOENIX_HOME/bin:$PATH
-
所有节点修改HBase配置文件 hbase-site.xml
# 在文件中添加如下命令 <!-- 建立二级索引,将业务需要的数据联立建立索引,方便查询 --> <property> <name>hbase.regionserver.wal.codec</name> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value> </property> <!-- 如果使用了 hbase 中的自定义 namespace,不仅仅使用default --> <!-- 那么在phoenix中与之对应的是schema的概念,但是默认并没有开启,需要在增加以下配置项 --> <property> <name>phoenix.schema.isNamespaceMappingEnabled</name> <value>true</value> </property>
-
把hbase-site.xml覆盖拷贝到/export/soft/phoenix-hbase-2.4-5.1.3-bin/bin
-
把解压出的如下四个jar放到所有节点的/export/soft/hbase/hbase-2.4.11/lib目录下
注意:其他四个不要放,会导致所有Region都挂掉或sqlline.py卡死
-
删除ZK中的hbase元数据信息,进入ZK客户端
deleteall /hbase
-
删除HDFS上的/hbase目录
hdfs dfs -rm -r /hbase
不进行6、7可能会出现Error: ERROR 1012 (42M03): Table undefined. tableName=SYSTEM:CATALOG (state=42M03,code=1012)
-
启动HBase,在启动HBase后要监视Region Server和Master的存活状态,注意看WebUI中HBase的日志。启动/phoenix-hbase-2.4-5.1.3-bin/bin目录下的sqlline.py。在WebUI中可看到Phoenix的建表。
14.3、语法
退出命令
!exit
1、建表
在phoenix中,默认情况下,库名,表名,字段名等会自动转换为大写,若要小写,使用双引号。
CREATE TABLE IF NOT EXISTS student(
id VARCHAR NOT NULL primary key,
C1.name VARCHAR,
C1.age VARCHAR,
C1.sex VARCHAR);
2、查看表信息
!desc STUDENT
3、删除表
drop table student;
4、数据插入/更新
upsert into student values ('00001','zhangsan','13','man');
upsert into student (id,age) values ('00001','14');
5、查询数据
select * from student;
6、删除数据
delete from student where id='00001';
7、分页
select * from student limit 10 offset 10;
8、创建视图
名称空间和表名一样,列族名和列名也要一一对应
create view '名称空间','表名'(
rowkey对应列名 varchar primary key,
列族名.列名 varchar,
);
14.4、Phoenix预分区
1、按照rowkey分区
CREATE TABLE IF NOT EXISTS student1(
id VARCHAR NOT NULL primary key,
C1.name VARCHAR,
C1.age VARCHAR,
C1.sex VARCHAR)
split on ('00003','00005','00007');
2、按照数量分区
CREATE TABLE IF NOT EXISTS student2(
id VARCHAR NOT NULL primary key,
C1.name VARCHAR,
C1.age VARCHAR,
C1.sex VARCHAR) salt_buckets=6;
14.5、JDBC开发
-
修改hbase-site.xml
同安装时一样修改hbase-site.xml,后面添加
<property> <name>phoenix.schema.isNamespaceMappingEnabled</name> <value>true</value> <description>命名空间开启</description> </property> <property> <name>hbase.regionserver.wal.codec</name> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value> <description>二级索引支持</description> </property>
-
添加maven
<dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-client-hbase-2.4</artifactId> <version>5.1.2</version> </dependency>
-
代码
@Test public void testPhoenixClient() throws SQLException, ClassNotFoundException { Class.forName(PhoenixDriver.class.getName()); String url="jdbc:phoenix:192.168.132.100:2181"; Connection connection = DriverManager.getConnection(url); PreparedStatement preparedStatement = connection.prepareStatement("select * from student "); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getString(1) + resultSet.getString(2)); } connection.close(); }
14.6、二级索引
Phoenix的索引存储在HBase里。
-
全局索引
适用读多写少,会额外创建一张索引表,分布在HBase全部节点,不一定与数据表在一台节点上。负载大多数发生在写入时,当构建了全局索引,Phoenix会拦截数据更新操作,会构建索引的更新,开销较大。如select引用了其他非索引列,该索引不生效。一般与覆盖索引搭配使用。
create index 索引名 on 表名(列1,列2…)
-
本地索引
适合写多读少场景,本地索引与业务数据在同一台节点上,查询自动使用本地索引,减少网络开销。即使select引用非索引字段也会应用本地索引。
create local index 索引名 on 表名(列1,列2…)
-
覆盖索引
把要查询的列直接放到索引中,不需要再次查询整表。即在列1,列2上创建索引,把列3数据捆绑在索引中,不需再查整表。与全局索引结合使用,省一次查询操作。
create index 索引名 on 表名(列1,列2)include (列3)
-
函数索引
基于表达式创建索引
create index 索引名 on 表名(函数)
14.7、Phoenix整合hive
待续