postgres 把一个表的值转成另一个表的字段名_Phoenix系列创建Phoenix映射表
目前,在公司小部分的业务场景中有用到 Phoenix,但也仅限基于 Phoenix 的二级索引机制来进行查询上的优化。虽然使用的频次不大,但偶尔用到时,有些语句的使用方式和注意事项总记不太熟,每次都需要一顿谷歌和百度,然后从五花八门的文章中摄取着自己需要的信息。
本文是 Phoenix 系列的第一篇文章,我打算从 Phoenix 映射表的创建开始说起。Phoenix 映射表的创建虽然看起来很简单,但其中的细节和潜在的坑着实也不少,且容我慢慢道来。
本文详细记录了 Phoenix 映射表的基本创建方式,以及我自己额外的一些思考和测试,如果文章中有描述不当的地方,还望大家多多指教,也欢迎大家在留言区踊跃发言。
1. 我的软件环境
在开始正式介绍之前,还是先来说明下我 Phoenix 的版本。文中涉及到的关于 Phoenix 的使用小示例,基于的版本分别是PHOENIX-4.14.0-cdh5.13.2
和PHOENIX-5.0.0-cdh6.2.0
,其中两个 Phoenix 对应的 HBase 的版本分别是HBase 1.2.0-cdh5.13.1
和HBase 2.1.0-cdh6.3.1
。如果没有特别的说明,所选示例在两个版本中运行方式以及结果是一样的。
2. 关于 Phoenix
Phoenix 是一款优秀的基于 HBase 的数据库中间件,由 Apache 官方出品,圈内共识,Apache 出品,必属精品,当然,烂尾的除外哈。Phoenix 把用户输入的 SQL 语句翻译成 HBase 底层的查询 API,简化了 HBase 客户端的查询方式,让用户可以使用标准的 SQL 语句来查询 HBase 表里的数据。配合 Phoenix 的二级索引机制,Phoenix 可以实现更加方便和复杂的 HBase 数据查询场景。有关 Phoenix 更深入的介绍,可以前往其官网查看。http://phoenix.apache.org/
3. 在 Phoenix 中创建不存在的 HBase 表的映射表
Phoenix 创建表的语句与 MySql 的语法有点相似,但需要关注的细节也有很多。
create table "user"( " id" VARCHAR PRIMARY KEY, "info"."name" VARCHAR, "info"."age" VARCHAR) column_encoded_bytes=0;
把上述建表语句 copy 到 Phoenix 的 shell 下,运行后查看我们创建的表的信息。
同时,在 HBase 的 default 命名空间中,也自动创建出了一张名叫 user 的表。
跟以普通方式创建的 HBase 表相比,除了常规的表描述信息之外,Phoenix 创建的表还多了一些协处理器等的描述信息。望文生义,这些协处理器大致与 Scan、索引创建等等操作有关。
让我们再来解读下这个简单的建表语句,“user”是表名,id 作为主键,也即是 HBase 表中的 RowKey,“info”最终在 HBase 中体现为表的列簇,“name","age"就是表的字段名,紧随其后的是列的类型,统一都是 VARCHAR,也即字符串,字段名默认可以为空,如果强制不为空,则为其加上 NOT NULL。"id"因为要作为 RowKey,所以一定不能是空的。最后一行 column_encoded_bytes=0 表示需要禁用列映射规则,否则会降低查询性能,所以一般情况下这里都置为 0。
到这里大家也许会发现,表名、字段名、列簇名都被引号包括,如果我不指定引号呢?让我们先删除表,然后重新运行如下的建表语句:
删除表的操作是 drop table "user",如果待删除的表不存在,就会抛出异常,如果想要避免表不存在的异常,则需要加上表是否存在的判断,即运行 drop table if exists "user"。删除表的同时,底层映射的 HBase 表也一同被删除,这绝对是你删库跑路的利器,所以生产环境下还是谨慎使用吧。
create table user( id VARCHAR PRIMARY KEY, info.name VARCHAR, info.age VARCHAR) column_encoded_bytes=0;
然后查看下我们重新创建的表:
首先我们的表名被转成了大写,再 select 下数据。
查看下 HBase 表:
如上图所示,引号的作用应该很明显了吧,Phoenix 中表名、列簇名、字段名如果不加引号,会被默认转成大写。
4. 在 Phoenix 中创建存在的 HBase 表的映射表
接着,我们删除刚刚创建的 user 表。再来尝试如下的建表方式。首先在 HBase 的命令行下创建一张名叫 user 的表,其列簇是 info,create user,info
。此时 user 表就是一个普普通通的 HBase 表,然后运行如下建表语句:
create table "user"( id VARCHAR PRIMARY KEY, info.name VARCHAR, info.age VARCHAR) column_encoded_bytes=0;
上述建表语句中我故意把 user 加引号,是为了确保在 Phoenix 中创建的表就是小写的名字,而不会在 HBase 中重新生成一张名叫 USER 的表。运行完查看下我们的 HBase 表。多了一个名叫 INFO 的列簇。所以,我们只有严格保证这些大小写一一对应,才能保证 Phoenix 表与 HBase 确立正确一致的映射关系,重新运行如下建表语句。
create table "user"( " id" VARCHAR PRIMARY KEY, "info"."name" VARCHAR, "info"."age" VARCHAR) column_encoded_bytes=0;
所以,我们可以先提前创建 HBase 表,再去创建该表的 Phoenix 映射表,保证大小写一一对应,同样可以达到如小节 3 中的效果。
5. 创建带有 schema 的 Phoenix 表
直接运行如下建表语句:
create table "person"."user"( " id" VARCHAR PRIMARY KEY, "info"."name" VARCHAR, "info"."age" VARCHAR) column_encoded_bytes=0;
如果这个名叫 person 的 schema 不存在就会遇到建表的异常。
运行 create schema "person"来创建 schema,同样需要注意大小写。能正确创建 schema 的前提是需要在 HBase 的服务端和 Phoenix 的客户端增加如下配置:
<property> <name>phoenix.schema.isNamespaceMappingEnabledname> <value>truevalue>property><property> <name>phoenix.schema.mapSystemTablesToNamespacename> <value>truevalue>property>
schema 创建完成之后,我们的表就能被正常创建了,Phoenix 的表创建完毕后,HBase 中会自动创建名为 person 的 namespace 和名为 person:user 的表。
6. 创建 Phoenix 表指定预分区
默认情况下创建的 Phoenix 表映射的 HBase 底层表只有一个分区,但是如果你的表数据很大,导数据时一个分区能把你急的肝疼。创建 Phoenix 表时预分区的方法有两种,一种是提前创建一个具有预分区的 HBase 表,然后再创建 Phoenix 表来映射已经存在的表;另一种则是创建 Phoenix 表的同时指定好预分区的信息。
示例语句如下:
create table "person"."user"( "id" VARCHAR PRIMARY KEY, "info"."name" VARCHAR, "info"."age" VARCHAR) column_encoded_bytes=0 SPLIT ON ('1','2','3','4','5','6','7','8','9');
然后在 HBase 的表监控界面上,你就可以看到如下的分区信息:
还有一种比较糟糕情况是,你的 HBase 表提前创建好了,大量数据也导入了表中,此时你才想起来需要创建 Phoenix 表。在大量数据存在的前提下,在 Phoenix shell 中直接创建映射表,十有八九会遇到客户端超时的异常,貌似不太影响使用,只是不知道会不会数据映射不完整。目前对于这种情况还没找到合适的解决办法,只能在创建表的开始阶段就好好规划下是否需要创建 Phoenix 表以及创建表时的预分区等,尽量避免出现这样的尴尬状况。
7. 各种数据写入后的映射情况
在这一小节里将说明 HBase 的各种写入方式写入的数据能否在 Phoenix 中正常绑定,以及 Phoenix 端数据写入后能否在 HBase 表中顺利查到。
对于 HBase 的数据写入方式,我在这里主要分成 bulkload 和普通的 hbase client api 写入,首先来测试下 client api 的数据写入方式,简单起见我直接在 shell 下 put 一些数据。
再来查看 Phoenix 中的数据,数据正常绑定。
接着测试在 phoenix 表插入一些数据,然后观察 HBase 的数据变化。
upsert into "person"."user" ("id","name","age") values('2', 'leo2','17');
就不贴图了,Phoenix 和 HBase 两边的数据是一一对应的。
那继续来测试 bulkload 的方式导入数据,然后观察 Phoenix 和 HBase 两边的数据情况吧!
测试之前,我们先用truncate_preserve 'person:user'
命令清空 user 表里的数据。
准备一些测试数据,然后上传至 hdfs 的某一个测试目录。
使用如下命令先把 csv 文件转换成 hfile:
hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.separator="," -Dimporttsv.bulk.output=/user/leo_jie/user_test_hfile -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:age person:user /user/leo_jie/user_test.csv
继续运行如下命令,以 bulkload 的方式把数据导入 person:user 表里:
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles -Dcreate.table=no /user/leo_jie/user_test_hfile person:user
以上命令成功运行结束后我们来检查下 HBase 和 Phoenix 两边的数据:HBase:
Phoenix:
上述的测试是为了说明,数据不同的写入方式对 HBase 和 Phoenix 两边的数据绑定是否有不同的影响,而目前看来,似乎没有什么特殊的地方。后续还会测试数据不同的写入方式,对 Phoenix 索引数据的影响,在那种场景下,还会是一样的结果吗?让我们拭目以待!
8. 创建多个列簇 Phoenix 映射表
这一小节补充下多列簇 Phoenix 映射表的创建,直接上建表语句:
create table "person"."user2"( "id" VARCHAR PRIMARY KEY, "info"."name" VARCHAR, "info"."age" VARCHAR, "info2"."name" VARCHAR, "info2"."age" VARCHAR, "info2"."address" VARCHAR) column_encoded_bytes=0;
以 put 的方式插入一些数据,然后在 Phoenix 中做以下查询:
对于所属不同列簇但名称相同的字段的查询,一定要显示指定字段所属的列簇名,不然查询时会报异常。除此之外,跟单列簇创建方式相比,倒也没啥特别之处了。
9. Phoenix 视图
类似 MySql 等关系型数据库中的视图,Phoenix 也有自己的视图概念,其视图的创建方式与表的创建语句类似。如果单纯只是为了查询数据,强烈建议为 HBase 表创建 Phenix 的视图映射,此时视图的删除对 HBase 的源表不会造成任何影响。
之前在倒腾 Phoenix 视图的时候,频繁遇到各种各样的报错,直至现在,对于其中的有些异常,依旧不明就里。下面先直接演示能正确创建视图的语句吧!
首先创建一张 HBase 表,create 'USER','INFO'
不要为这张表创建其 Phoenix 映射表,然后运行如下创建视图的语句。
create view USER(ID VARCHAR PRIMARY KEY,INFO.NAME VARCHAR,INFO.AGE VARCHAR);
在 HBase 中插入一些数据,观察视图中的数据是否会实时更新。答案是,在 HBase 中插入数据,Phoenix 视图会实时更新数据。
那么以 bulkload 的方式更新数据呢?根据上文中提到的测试方法,我们再来实施一下。答案是,以 bulkload 的方式把数据导入 HBase 中,Phoenix 依旧会实时更新数据。
反过来,我们是否可以在 Phoenix 中 upset 数据呢?
upsert into USER (ID,NAME,AGE) values('111', 'leo111','17');
视图是只读的,不能做修改之类的操作。此时删掉视图,对 HBase 源表是没有影响的。
drop view USER;
scan 'USER'
再来说明一下当初折腾视图时遇到的各种各样的异常。
「HBase 源表不存在而直接创建视图」
看来 Phoenix 视图创建跟 Phoenix 表创建有很大不同啊。
「HBase 源表存在且 Phoenix 映射表也存在」
删除掉原来的测试表,然后直接用创建 Phoenix 表的方式,同时创建出 HBase 的源表。
create table USER(ID VARCHAR PRIMARY KEY,INFO.NAME VARCHAR,INFO.AGE VARCHAR)column_encoded_bytes=0;
此时我们再来运行视图创建语句。
create view USER(ID VARCHAR PRIMARY KEY,INFO.NAME VARCHAR,INFO.AGE VARCHAR);
如果直接运行这个语句,不出意外一定会报错,报错信息如下:Error: ERROR 1036 (42J04): Cannot modify the primary key of a VIEW if last PK column of parent is variable length. columnName=USER.ID (state=42J04,code=1036)
table 的名字是 USER,view 的名字也是 USER,但这真的是报错的根本原因吗?那让我们换一个名字来试试看。
create view USER_VIEW(ID VARCHAR PRIMARY KEY,INFO.NAME VARCHAR,INFO.AGE VARCHAR);
继续报错:
Error: ERROR 505 (42000): Table is read only. (state=42000,code=505),又回到了我们刚开始的异常,HBase 源表不存在而直接创建视图。这时候如果你一顿谷歌加百度,十有八九会遇到类似这样的视图创建语句。
create view USER_VIEW(ID VARCHAR PRIMARY KEY,INFO.NAME VARCHAR,INFO.AGE VARCHAR) as select * from USER;
指定查询数据集,也就是 select 的语句,再映射到视图 USER_VIEW 上,依旧报错:
Error: ERROR 1036 (42J04): Cannot modify the primary key of a VIEW if last PK column of parent is variable length. columnName=USER_VIEW.ID (state=42J04,code=1036)
聪明的你一定会这样修改上述的语句。
create view USER_VIEW as select * from USER;
这样的创建语句其实很类似 hive 还有其他的一些关系型数据库。如果,你还想创建指定列的视图呢?
create view USER_VIEW_NAME as select NAME from USER;
你以为这样写就可以了吗?脸黑的我又遇见了这样的报错。
Error: ERROR 604 (42P00): Syntax error. Mismatched input. Expecting "ASTERISK", got "NAME" at line 1, column 38. (state=42P00,code=604)
百度了一波,从大佬的博客里了解到,目前在 Phoenix 创建视图时,子句中不能选择字段,只能用*号,否则就会报如上错误。
是否可以创建语法更复杂的视图呢?例如,我已经有了一张 USER 表,再创建一张 PAY 表,记录每个用户的花销。然后以 JOIN 的方式创建视图 USER_PAY_VIEW。
当前版本的视图支持的语法比较有限,SELECT 中不能有复杂的语法,否则解析时会无法判断结束标记。
视图使用时,一定要注意,在没有创建索引的情况下,不要瞎写 SQL 语句,什么 group by,order by。否则一旦表里的数据量过大,你十有八九能遇到全表扫描,严重情况下影响线上业务。这样的规则,对表的查询同样适用。
10. 最后
最后来总结一下 Phoenix 的常规使用吧。Phoenix 表创建时要注意大小写,如果需要使用小写,那么请给表名,列簇名,字段名加上英文类型的双引号;如果你的 HBase 表数据量过大,创建表时,请尽可能提前把对应的 Phoenix 映射表也创建出来吧,最后再导入数据;针对建表时的预分区操作,文中也提到了两种方式。如果对表仅有查询需要,那么请考虑创建视图,但视图的使用又有很大的限制,使用不当就会导致全表扫描,不仅影响查询效率,还会影响线上的业务。
11. 参考链接
- https://blog.csdn.net/github_39577257/article/details/95968727
据说,关注我的人都找到了对象?
postgres 把一个表的值转成另一个表的字段名_Phoenix系列创建Phoenix映射表相关推荐
- postgres 把一个表的值转成另一个表的字段名_用LUT来做一个可动态配置的卷积核...
引言 由于卷积核数据在计算过程中保持不变,更新较慢.这样就可以利用LUT来存储权重并同时进行乘法运算.LUT乘法器的实现很早就已经研究过,本论文正是在此基础上,提出了用于实现可配置的卷积实现方法.基于 ...
- postgres 把一个表的值转成另一个表的字段名_Postgres索引那些事
本文转自Greenplum中文社区官方网站:greenplum.cn: 最实时最权威的Greenplum技术文档.博客,以及热点新闻,请关注greenplum.cn: Postgres内部提供了很多种 ...
- postgres 把一个表的值转成另一个表的字段名_希望一个数据同步,包治百病
小姐姐味道[ID:xjjdog] 作者:十年架构,日百亿流量经验,与你分享. 哎!这是一个脏活,而且是个高风险的活. 大多数情况下,应用架构设计不好,引入什么新存储,引入什么DDD,治标不治本,都是扯 ...
- 如何把一个数组的值赋给另一个数组
java中的数组 一维数组中把一个数组的值赋给另外一个数组 public class test {public static void main(String[] args) {int[] array ...
- mysql join 去重_MySQL Update inner join数据库去重,以及根据一张表的值更新另一张表...
1 问题来源 这几天在项目中遇到一个问题:由于前期设计不合理,导致后期用户录入数据时,基础数据表中有重复多余数据.如下: 出现两个 2G网络测试手机 这样类似的基础数据,直接后果就是用户在使用这个基础 ...
- 外汇天眼:Apple与MetaQuotes之争!谁是下一个Apple?谁会成下一个MT4/5?
手机巨头Apple 从其应用商店App Store中下架领先的交易软件MetaTrader4(MT4)和 MetaTrader5(MT5)引发了外汇市场热议. 虽然截止发稿,Apple以及交易软件MT ...
- mysql怎么把值更新成space,MySQL表的碎片整理和空间回收小结
MySQL表碎片化(Table Fragmentation)的原因 关于MySQL中表碎片化(Table Fragmentation)产生的原因,简单总结一下,MySQL Engine不同,碎片化的原 ...
- 注册表把html设置成桌面,[注册表] 将Windows 10默认应用程序设置页面添加到桌面右键菜单中...
从Windows 10初始版本开始微软就已调整默认程序配置策略,即强制用户设置关联的默认程序不允许软件设置. 这也是很多用户经常在通知栏里看到某某文件格式被重置的原因,因为软件安装后设置的会被微软重置 ...
- 在PS里要怎么样才能把一个图片的数字改成另一个数字,还要看不出来?
转自: http://zhidao.baidu.com/link?url=fGmHdcGZu76sRD3VQWxoQwQIDps5qlATz2tVPcggPMndChrXq3c9OfxloMZxHsY ...
最新文章
- Android碎片化难题:手游兼容性测试应该适配哪些机型?
- Linux内核调试的方式以及工具学习
- ARM体系结构及内核回顾总结(一)
- wordpress学习笔记
- sql server死锁的查询和解除
- AngularDart4.0 指南- 显示数据
- scala与java混合编译出现的问题
- java queue 线程安全_详解Java高并发——设计线程安全的类
- .net单点登录demo_图文并茂,为你揭开“单点登录“的神秘面纱
- 一个十二年老程序猿的碎碎念
- 极光开发者周刊【No.0827】
- javascript计算两个时间差
- 博客网页设计制作 简单静态HTML网页作品 DIV CSS个人网页作业成品 dreamweaver学生个人博客网站模板
- 聊天界面的制作(三)——表情列表发送功能
- WebXR 技术调研 - 在浏览器中构建扩展现实(XR)应用
- SMTP;ESMTP
- 【玩转华为云】手把手教你利用ModelArts识别偶像的声音
- 产品不良率计算公式--如PPM,DPPM,DPMO等
- JS实现腾讯地图搜索信息下拉以及定位...
- .Net Core 2.1 JWT Bearer 的认证
热门文章
- SAP Spartacus State
- ExpressionChangedAfterItHasBeenCheckedError - Expression has changed after it was checked
- SAP Spartacus user form页面的css设计重构
- Angular jasmine单元测试框架里expect.toHaveBeenCalled的工作原理
- SAP Spartacus需要补充url validation单元测试的地方
- Pricing in SAP CRM and Cloud for Customer
- 3d button - where is OS type and version detected
- when busy dialog closed iDuration renderFioriFlower jQuery Animation closeL
- Event handling in Angular
- Product guid got as Anchor