北京市住房与城乡建设部网站seo网站排名优化价格
为了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
- 前提条件
- 项目集成
- phoenix使用
- 建SCHEMA
- 建表
- 不指定列族
- 指定列族
- 主键
- RowKey加盐
- 二级索引
- 全局索引
- 覆盖索引
- 本地索引
- explain
前提条件
一个集成了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:2181driver-class-name: org.apache.phoenix.jdbc.PhoenixDriver# 如果不想配置对数据库连接池做特殊配置的话,以下关于连接池的配置就不是必须的# spring-boot 2.X 默认采用高性能的 Hikari 作为连接池 更多配置可以参考 https://github.com/brettwooldridge/HikariCP#configuration-knobs-babytype: com.zaxxer.hikari.HikariDataSourcehikari:minimum-idle: 100maximum-pool-size: 300# 允许最长空闲时间idle-timeout: 30000# 数据库连接超时时间,默认 30 秒,即 30000connection-timeout: 30000# 连接测试 sql 这个地方需要根据数据库方言差异而配置 例如 oracle 就应该写成 select 1 from dualconnection-test-query: SELECT 1# mybatis 相关配置
mybatis-plus:mapper-locations: classpath*:mapper/**/*.xmltype-aliases-package: com.example.phoenixdemo.entityconfiguration: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 {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);methodList.add(new Upsert());return methodList;}}
将UpsertInjector载入Spring容器
@Configuration
public class MybatisPlusHBasePhoenixConfig {@Beanpublic UpsertInjector upsertSqlInjector () {return new UpsertInjector();}
}
- 当作一个数据库来使用my baits 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