为什么Phoenix能让开发者通过SQL访问Hbase而不必使用原生的方式?引用Phoenix官网上的一句话:SQL is just a way of expressing what you want to get not how you want to get it. 即SQL不是一种数据操作技术,而是一种特殊的表达方式。只是表示你需要什么而不是你如何获得。
前提条件
一个集成了Phoenix的Hbase环境。搭建完成你会得到Phoenix地址和一个hbase-site.xml配置文件。
一个新的或者已有的要集成的项目。
项目集成
- 引入依赖。注意phoenix的版本号, 这个版本号要和你搭建的环境对应。 如5.0.0-HBase-2.0表示为5.0.0版本的phoenix和2.0版本的Hbase,如果不一致,很大可能报错。因此为了版本对应,最好还是先选定版本再搭建环境。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
- phoenix数据源和mybatis plus配置
spring:
datasource:
#Phoenix,zookeeper 地址
url: jdbc:phoenix:test-hbase.test.com:2181
driver-class-name: org.apache.phoenix.jdbc.PhoenixDriver
# 如果不想配置对数据库连接池做特殊配置的话,以下关于连接池的配置就不是必须的
# spring-boot 2.X 默认采用高性能的 Hikari 作为连接池 更多配置可以参考 https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 100
maximum-pool-size: 300
# 允许最长空闲时间
idle-timeout: 30000
# 数据库连接超时时间,默认 30 秒,即 30000
connection-timeout: 30000
# 连接测试 sql 这个地方需要根据数据库方言差异而配置 例如 oracle 就应该写成 select 1 from dual
connection-test-query: SELECT 1
# mybatis 相关配置
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
type-aliases-package: com.example.phoenixdemo.entity
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- 配置文件
将hbase-site.xml文件放入项目的resource目录下。如果没有特殊的配置,可以直接用下面这个配置。
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>phoenix.schema.isNamespaceMappingEnabled</name>
<value>true</value>
</property>
<property>
<name>phoenix.schema.mapSystemTablesToNamespace</name>
<value>true</value>
</property>
</configuration>
- 配置mybatis plus的Upsert操作
对于phoenix来说是没有单纯insert和update操作的,仅仅可以通过Upsert来进行(不存在新增,存在则更新)操作。因此需要配置mybatis plus的Upsert操作。
建立UpsertInjector类定义Upsert操作
public class UpsertInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new Upsert());
return methodList;
}
}
将UpsertInjector载入Spring容器
@Configuration
public class MybatisPlusHBasePhoenixConfig {
@Bean
public UpsertInjector upsertSqlInjector () {
return new UpsertInjector();
}
}
- 当作一个数据库来使用mybaits plus操作phoenix,如定义一个mapper
@Mapper
public interface HBasePhoenixBaseMapper<TestBean> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<TestBean> {
/**
* 不存在新增,存在则更新:因为已经载入,所以直接写个upsert方法就行
* @see com.baomidou.mybatisplus.extension.injector.methods.Upsert
* @param object 目标参数
*/
void upsert(TestBean object);
void select(TestBean object)
void delete(TestBean object)
}
更多关于my baits plus的使用这里就不赘述了。只要记得phoenix无法使用insert和update即可。
tips: phoenix连接创建时会打印一个info级别的堆栈,看着很像一个报错。然而这个并不是。
phoenix使用
建SCHEMA
CREATE SCHEMA IF NOT EXISTS "DEV_DEMO";
建表
不指定列族
基于Phoenix创建表时,如果没有指定列族的话,会默认自动创建一个名字为0列族。
CREATE TABLE DEV_DEMO.DEV_DEMO_TABLE (
ID UNSIGNED_LONG NOT NULL,
NAME VARCHAR,
AGE UNSIGNED_INT,
DELETED BOOLEAN,
CONSTRAINT K_DEV_DEMO_TABLE_PK PRIMARY KEY (ID)
);
指定列族
指定列族的时候需要注意,主键列不能指定,否则会报错。
CREATE TABLE DEV_DEMO.DEV_DEMO_TABLE (
"ID" UNSIGNED_LONG NOT NULL,
"person"."NAME" VARCHAR,
"person"."AGE" UNSIGNED_INT,
"person"."DELETED" BOOLEAN,
CONSTRAINT K_DEV_DEMO_TABLE_PK PRIMARY KEY (ID)
);
访问控制、磁盘和内存的使用统计都是在列族层面进行的,列族越多,在取一行数据时所需要参与 I/O、搜寻的文件就越多,所以,如果没有必要,不要设置太多的列族 官方推荐不要超过3个。(数据页的概念)
层级是 table-> region server(一个hbase集群有多个region server,类似于分库) -> region(类似于对表做的水平拆分,也就是分表) -> 列族(类似db做了垂直拆分,一个列族一个垂直表,对应hbase一个列族一个Store,同时他也对应数据页,也会发生类似页分类和页合并的flush
和compaction
操作)
一个Region Server可以管理多个Region, 一个Region只由一个Region Server管理。
大小写敏感的phoenix
注意,phoenix对大小写敏感。且phoenix客户端会自动转大写。因此如果你的schema名,表名或者字段名定义存在小写。则在指定schema名,表名,字段名时则需要加双引号(phoenix会自动将表名库名等转大写)。
因此这里建议无论大小写都加上双引号。 例:@TableName(“\“TEST_schema\”.\“test_table\””)
主键
每个主键都会产生成本,因为整个行键都附加到内存和磁盘上的每条数据。行键越大,存储开销越大
不同于数据库一个列只会记录一个主键,最多包含索引。 Hbase的列式存储使得每个列都会记录一份主键。
数据的存储是按照RowKey进行字典方式升序存储
范围查询hbase有scan的startrow endrow。
RowKey加盐
RowKey是按照字典序方式排序存储的,因此如果我们的主键定义本身就带有字典序的话,那么在写入时就会出现在某个阶段是一直在写入同一个region,而其它region则处于空闲状态。读取时同样可能出现由相关数据导致的热点。
为了避免这种热点,phoenix提供通过为主键自动加盐生成新的RowKey的方式来分散数据。在建表时指定盐桶大小(限制在1-256)即可(默认不执行加盐操作,id就是rowkey)。
CREATE TABLE DEV_DEMO.DEV_DEMO_TABLE (
ID UNSIGNED_LONG NOT NULL,
NAME VARCHAR,
AGE UNSIGNED_INT,
DELETED BOOLEAN,
CONSTRAINT K_DEV_DEMO_TABLE_PK PRIMARY KEY (ID)
) SALT_BUCKETS = 4;
加盐就是在原来key的基础上增加一个byte作为前缀,新rowKey的计算方式为
new_row_key = ((byte) (hash(original_key) % BUCKETS_NUMBER) + original_key
加盐的注意事项:
1)创建加盐表时不能再指定split key
2)加盐会影响根据RowKey的范围查询,因为数据分散到了不同的region
3)当可用block cache的大小>表数据大小时,slated buckett和region server数量相同,这样可以得到更好的读写性能。 但当表的数量很大时,基本上会忽略blcok cache的优化收益,大部分数据仍然需要走磁盘IO。比如对于10个region server集群的大表,可以考虑设计64~128个slat buckets。
二级索引
全局索引
和mysql创建索引的方式一致
create index indexName on tbName(colName1,colName2);
限制上同样有最左前缀限制。多列索引在满足前缀式的情况才会用到,如创建了A,B,C顺序的多列索引,当在where条件指定A条件、A B条件或者A B C条件均会走索引,但是 B C条件则无法走索引。
实现上:phoenix的全局索引,就是在HBase中创建一个真实的表,该索引表的rowkey是原表的索引列和rowkey组合而来的。
注意:当我们对原表进行select查询时,只有索引列中包含要查询的列时,才会走索引,phoenix没有二次查询,如果查询语句包含非索引列,就会直接去原表全表扫描而不是先走索引拿到原表的rowkey,再拿rowKey去原表查!
覆盖索引
所谓覆盖索引就是,就是把原数据再索引表中也存储一份,这样仅扫描索引表就可以读取到我们所需要的全部数据,不必再对原表进行扫描,只有从索引表中拿不到的数据,才会去原表中获取,从而提高检索速度。
create index indexName on tbName(colName1,colName2) include (colName3);
include的就是像通过索引查询的字段,但是这个字段又不想作为索引字段的处理。
全局索引适用于写少读多的情况,因为每个索引都是一个新表,写要操作n(索引数目)+1个表
本地索引
本地索引数据存储在同一数据表中的单独影子列族中。
RegionStartKey-索引名-索引键-索引值, 以列的值为键+记录的RowKey为新的RowKey,当以这些列为条件进行查询时,引擎可以通过检索相应的“键-值”数据快速找到目标记录
新增的这行数据的rowkey是由原表中的rowkey,索引列组成的。这个rowKey通过前缀设置为原rowkey的一部分来保证索引和数据在同一个region(类似于db中的数据页)中。
查询时可以通过rowkey加元数据得到具体的Region,但是使用索引时因为没有rowkey,所以在使用本地索引的读取时,必须检查每个Region(所有region server的所有Region)的数据,因为无法预先确定索引数据的确切Region。
本地索引适合写多读少的场景,因为索引数据和真实数据都是在同一张表中的。
本地索引的特点就是不管查询的数据索引表中有没有,都会先走索引。
create local index indexName on tbName(colName1,colName2);
可以看到,hbase本身并不擅长,因此查询方面方面如果有复杂查询,尽量引入其它组件(如es)记录 条件–>rowKey的映射关系。
explain
phoenix也能用explain来查看执行计划。
参考资料:
phoenix官网
Spring/Spring Boot 整合 Mybatis + Phoenix
Phoenix加盐表
shell命令
DBEAVER连接PHOENIX文章来源:https://www.toymoban.com/news/detail-607039.html
————————————————
版权声明:本文为CSDN博主「yue_hu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yue_hu/article/details/129082216文章来源地址https://www.toymoban.com/news/detail-607039.html
到了这里,关于【Java核心知识】spring boot整合Mybatis plus + Phoenix 访问Hbase与使用注意的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!