Hbase笔记
Hbase操作:
--namespace
--修改或者增加属性
hbase> alter_namespace 'ns1', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
--删除属性
alter_namespace 'ns1', {METHOD => 'unset', NAME=>'PROPERTY_NAME'}
--创建
hbase> create_namespace 'ns1'
hbase> create_namespace 'ns1', {'PROPERTY_NAME'=>'PROPERTY_VALUE'}
--详情
hbase> describe_namespace 'ns1'
--删除 必须是空的
drop_namespace 'zjq1'
-- 命名空间列表
hbase> list_namespace
hbase> list_namespace 'abc.*'
--表列表
list_namespace_tables 'ns1'
--table 的DDL操作
--显示所有表
list
--创建表 不指定库默认建在default上 创建的列族是按照字典序排的 VERSIONS表示保留几个版本
create 'zjq:test' ,{NAME => 'name',VERSIONS => 3}
create 'zjq:zjq', {NAME => 'A'} ,{NAME => 'B'} ,{NAME => 'C'}
create 'test' ,'name','age'
--详细信息 = desc
describe 'test'
describe 'zjq:zjq'
desc 'zjq'
desc 'zjq:zjq'
--alter 添加列族 列族区分大小写 有了的就不加 没有的就加上
alter 'test',NAME => 'FUCK',VERSIONS =>5
alter 'test',NAME => 'fuck'
alter 'test',{NAME => 'AGE1',VERSIONS =>1},{NAME =>'NAME1'}
--删除列族 name值区分大小写 大写删不掉
alter 'test' ,NAME=>'name' ,METHOD => 'delete'
alter 'test','delete' =>'fuck'
--修改versions
alter 'test',NAME => 'name',VERSIONS=>'5'
--删除表
--设置表可用
enable 'zjq:zjq'
--先设置不可用 再删除
disable 'zjq:zjq'
drop 'zjq:zjq'
--清空表数据 清空表的操作顺序为先disable,然后再truncate 自动会disable
truncate 'test'
--table的DML操作
点击查看代码
--添加数据 put '表名','row_key','列族:列名','value' 列族里面的列互不影响
put 'ns1:t1', 'r1', 'c1', 'value'
put 'zjq:zjq','1001','a:name','zhangsan'
put 'zjq:zjq','1001','a:age','22'
put 'zjq:zjq','1001','a:sex','nan'
put 'zjq:zjq','1001','b:school','sxxx'
put 'zjq:zjq','1001','b:class','5'
put 'zjq:zjq','1003','b:school','sxxx'
put 'zjq:zjq','1003','b:class','5'
--查询数据
--同一个row_key的全部 get只能看一行
get 'ns1:t1', 'r1'
get 'zjq:zjq','1001'
--同一个row_key的指定列族
get 't1', 'r1', 'c1'
get 'zjq:zjq','1001','b'
--多个列族
get 't1', 'r1', 'c1', 'c2'
get 'zjq:zjq','1001','b','a'
--指定列族的指定列
get 'zjq:zjq','1001','b:class','a:name'
get 'zjq:zjq','1001',['b:class','a:name']
--扫描数据 scan 扫描全表
scan 'zjq:zjq'
--指定列族的列 scan 'hbase:meta', {COLUMNS => 'info:regioninfo'}
scan 'zjq:zjq', {COLUMNS => 'a'}
scan 'zjq:zjq', {COLUMNS => 'a:name'}
--显示指定列或者指定列族的字段
scan 'ns1:t1', {COLUMNS => ['c1', 'c2'], LIMIT => 10, STARTROW => 'xyz'}
scan 'zjq:zjq',{COLUMNS=>'b' ,LIMIT=>5,STARTROW=>'1001'} --??
scan 'zjq:zjq',{COLUMNS=>'b:id' ,STARTROW=>'1001',LIMIT=>5}
--通过 STARTROW STOPROW 限制行数 [)
scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001'}
scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001',STOPROW=>'1003'}
--按照字典序的特征 使用acii码灵活控制输出的开闭区间
字典序中比0小的符号还是有的
/*
hbase(main):063:0> scan 'zjq:zjq',{COLUMNS=>'b'}
ROW COLUMN+CELL
1001 column=b:class, timestamp=1624621820960, value=5
1001 column=b:school, timestamp=1624621813233, value=sxxx
1002 column=b:id, timestamp=1624622557896, value=24
1002! column=b:school, timestamp=1624624553329, value=sxxx
10021 column=b:class, timestamp=1624623192141, value=5
10021 column=b:school, timestamp=1624623204682, value=sxxx
10021! column=b:school, timestamp=1624624534152, value=sxxx
10021| column=b:school, timestamp=1624624518262, value=sxxx
1003 column=b:class, timestamp=1624623185968, value=5
1003 column=b:school, timestamp=1624623183673, value=sxxx
7 row(s)
Took 0.0265 seconds
hbase(main):057:0> scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001',STOPROW=>'1002'}
ROW COLUMN+CELL
1001 column=b:class, timestamp=1624621820960, value=5
1001 column=b:school, timestamp=1624621813233, value=sxxx
1 row(s)
Took 0.0263 seconds
hbase(main):059:0> scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001',STOPROW=>'10021'}
ROW COLUMN+CELL
1001 column=b:class, timestamp=1624621820960, value=5
1001 column=b:school, timestamp=1624621813233, value=sxxx
1002 column=b:id, timestamp=1624622557896, value=24
1002! column=b:school, timestamp=1624624553329, value=sxxx
3 row(s)
Took 0.0237 seconds
hbase(main):056:0> scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001',STOPROW=>'1002!'}
ROW COLUMN+CELL
1001 column=b:class, timestamp=1624621820960, value=5
1001 column=b:school, timestamp=1624621813233, value=sxxx
1002 column=b:id, timestamp=1624622557896, value=24
2 row(s)
Took 0.0505 seconds
hbase(main):058:0> scan 'zjq:zjq',{COLUMNS=>'b' ,STARTROW=>'1001',STOPROW=>'1002|'}
ROW COLUMN+CELL
1001 column=b:class, timestamp=1624621820960, value=5
1001 column=b:school, timestamp=1624621813233, value=sxxx
1002 column=b:id, timestamp=1624622557896, value=24
1002! column=b:school, timestamp=1624624553329, value=sxxx
10021 column=b:class, timestamp=1624623192141, value=5
10021 column=b:school, timestamp=1624623204682, value=sxxx
10021! column=b:school, timestamp=1624624534152, value=sxxx
10021| column=b:school, timestamp=1624624518262, value=sxxx
6 row(s)
Took 0.0618 seconds
*/
--修改数据
--更新数据(update)也是使用put 是覆盖的策略 定位之后直接刷新
put 'zjq:zjq','1001','b:class','55667788'
--扫描指定版本之前的所有数据 包括删除和更新之后的 只是timestamp不同 hbase只显示时间戳大的
scan 'zjq:zjq',{RAW=>true,VERSIONS=>3}
--删除数据
--删除列族中的一列的最新版本的数据
delete 'ns1:t1', 'r1', 'c1', ts1(时间戳)
delete 'zjq:zjq','1001','b:class'
--执行之后 type=Delete type被标记为Delete
--修改之后的数据 需要执行多次 才能查询不出来 因为hbase默认是显示当前时间戳最大的
1001 column=b:class, timestamp=1624626962683, type=Delete
1001 column=b:class, timestamp=1624626962683, value=aaaaaa
1001 column=b:class, timestamp=1624626412000, type=Delete
1001 column=b:class, timestamp=1624626412000, value=55667788
1001 column=b:class, timestamp=1624621820960, type=Delete
1001 column=b:class, timestamp=1624621820960, value=5
--删除列族 一列所有版本的数据 type标记是DeleteColumn 直接不匹配b:school所有版本的数据
deleteall 'zjq:zjq','1001','b:class'
1003 column=b:school, timestamp=1624630451873, type=DeleteColumn
1003 column=b:school, timestamp=1624630398015, value=xxxxx
1003 column=b:school, timestamp=1624623183673, value=sxxx
--删除一列 type标记是DeleteFamily 将row_key这一列都完全删除
deleteall 'zjq:zjq','10021'
scan 'zjq:zjq',{RAW=>true,VERSIONS=>3}
10021 column=a:, timestamp=1624630729325, type=DeleteFamily
10021 column=b:, timestamp=1624630729325, type=DeleteFamily
10021 column=b:class, timestamp=1624623192141, value=5
10021 column=b:school, timestamp=1624630701020, value=delete
10021 column=b:school, timestamp=1624623204682, value=sxxx
这个时候再put进去 因为新的时间戳是最大的 所以不会受到DeleteFamily的影响
HbaseAPI操作:
点击查看代码
Hbase优化
1.提前规划好Hbase的分区 提高性能
--1.预分区
create 'zjq:zjq','test',SPILITS => ['1000','2000','3000','4000']
分为五个分区 负无穷到1000 1000-2000 2000-3000 3000-4000 4000-正无穷
--2.十六进制预分区 生成15个分区按照十六进制 需要吧rowkey也转成十六进制 才能正确放到自己的分区
create 'staff2','info',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
--3.按照文件中设置的规则预分区
创建splits.txt文件内容如下:
aaaa
bbbb
cccc
dddd
--执行命令
create 'staff3','info',SPLITS_FILE => 'splits.txt'
分为五个分区 负无穷-aaaa aaaa-bbbb bbbb-cccc cccc-dddd dddd-正无穷
--4.使用JavaAPI创建预分区
2.RowKey设计
一条数据的唯一标识就是rowkey,那么这条数据存储于哪个分区,取决于rowkey处于哪个一个预分区的区间内,设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜。
--1 生成随机数,hash,散列值
比如:
原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,SHA1后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,SHA1后变成:7b61dec07e02c188790670af43e717f0f46e8913
在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的rowKey来Hash后作为每个分区的临界值。
--2 字符串反转
20170524000001转成10000042507102
20170524000002转成20000042507102
这样也可以在一定程度上散列逐步put进来的数据。
--3 拼接字符串
20170524000001_a12e
20170524000001_93i7
3.基础优化
1.Zookeeper会话超时时间
hbase-site.xml
属性:zookeeper.session.timeout
解释:默认值为90000毫秒(90s)。当某个RegionServer挂掉,90s之后Master才能察觉到。可适当减小此值,以加快Master响应,可调整至60000毫秒。
2.设置RPC监听数量
hbase-site.xml
属性:hbase.regionserver.handler.count
解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
3.手动控制Major Compaction
hbase-site.xml
属性:hbase.hregion.majorcompaction
解释:默认值:604800000秒(7天), Major Compaction的周期,若关闭自动Major Compaction,可将其设为0
4.优化HStore文件大小
hbase-site.xml
属性:hbase.hregion.max.filesize
解释:默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。
5.优化HBase客户端缓存
hbase-site.xml
属性:hbase.client.write.buffer
解释:默认值2097152bytes(2M)用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。
6.指定scan.next扫描HBase所获取的行数
hbase-site.xml
属性:hbase.client.scanner.caching
解释:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。
7.BlockCache占用RegionServer堆内存的比例
hbase-site.xml
属性:hfile.block.cache.size
解释:默认0.4,读请求比较多的情况下,可适当调大
8.MemStore占用RegionServer堆内存的比例
hbase-site.xml
属性:hbase.regionserver.global.memstore.size
解释:默认0.4,写请求较多的情况下,可适当调大
--Phoenix
--Phoenix是HBase的开源SQL皮肤。可以使用标准JDBC API代替HBase客户端API来创建表,插入数据和查询HBase数据
Phoenix特点
1)容易集成:如Spark,Hive,Pig,Flume和Map Reduce;
2)操作简单:DML命令以及通过DDL命令创建和操作表和版本化增量更改;
3)支持HBase二级索引创建。
Phoenix的架构分为两种: thin client 和 thick client
1.
thin client: 需要启动QueryServer服务
--启动
1).queryserver.py start
2).sqlline-thin.py Ava01:8765
2.
thick client:在客户端完成几乎所有操作
--启动
sqlline.py (等价于 sqlline.py localhost:2181 )
--去找的是zk的端口
sqlline.py Ava01:2181,Ava02:2181,Ava03:2181
2.Phoenix 操作
-- 注意:在phoenix中,schema名,表名,字段名等会自动转换为大写,若要小写,使用双引号,如"student"
-- 除了insert关键字改了 其他的可以使用sql直接操作
--创建schema == namespace
create schema "fpx";
--
use "fpx"
-- 建表 建表的时候必须要有主键 对应hbase的row_key
--单个主键 hbase fpx:tian 非主键列只能在具有不可变行的表上声明为非空
--if not exists phoenix 对于已经存在的表 不会进行任何操作
create table if not exists "fpx"."tian"(
id varchar primary key,
name varchar ,
score bigint
)column_encoded_bytes=NONE;
--列联合主键 联合主键的构成列都必须是非空的
create table if not exists "fpx"."lwx"(
id varchar not null,
name varchar not null,
score bigint
CONSTRAINT my_pk PRIMARY KEY (id, name)
);
-- 插入数据 关键字是upsert
upsert into "fpx"."tian" values ('001','tian',123);
--在habse中scan表
hbase(main):015:0> scan 'fpx:tian'
ROW COLUMN+CELL
001 column=0:\x00\x00\x00\x00, timestamp=1624874203553, value=x
001 column=0:\x80\x0B, timestamp=1624874203553, value=tian
001 column=0:\x80\x0C, timestamp=1624874203553, value=\x80\x00\x00\x00\x00\x00\x00{
--出现的问题
1. 为了匹配那种只有主键有数 其他都是空的字段 所有会自动设置一个 column=0:\x00\x00\x00\x00, timestamp=1624874203553, value=x 类似于这种的列来记录row_key
2. 字段名转码的问题 Phoenix 默认会在创建表的时候对字段名进行编码 一共有5种模式 :
Config/Property Value :Max # of columns
1 255
2 65535
3 16777215
4 2147483647
NONE no limit(theoretically)
模式为1时 最多可以有255个字段
可以通过建表时 column_encoded_bytes=NONE 设置不进行编码
create table if not exists "fpx"."tian2"(
id varchar primary key,
name varchar ,
score bigint
)column_encoded_bytes=NONE;
或者 column_encoded_bytes=0
3. value值为啥会显示成这样?
--问题 : 表映射中数值类型的问题 :为什么hbase建表 hbase访问 Phoenix建表 Phoenix访问都没有问题 但是不是同一个东西建表 另外一个访问就会出现问题
--删除表
drop table "fpx"."tian"
--退出命令行
!quit
-- 表的映射 和 视图映射
默认情况下,直接在HBase中创建的表,通过Phoenix是查看不到的。如果要在Phoenix中操作直接在HBase中创建的表,则需要在Phoenix中进行表的映射。映射方式有两种:视图映射和表映射。
--'zjq:test' 结构 只有一个列族
ROW COLUMN+CELL
1001 column=name:name, timestamp=1624877337153, value=222
--视图映射 row_key作为主键 视图只能看 不能操作 字段名要和列族的字段名对上 否则查出来数据是空的
create view "zjq"."test"(id varchar primary key,"name"."name" varchar);
--删除视图
drop view "zjq"."test";
--表映射
(1)HBase中不存在表时,可以直接使用create table指令创建需要的表,系统将会自动在Phoenix和HBase中创建person_infomation的表,并会根据指令内的参数对表结构进行初始化。
(2)当HBase中已经存在表时,可以以类似创建视图的方式创建关联表,只需要将create view改为create table即可
create table "zjq"."test"(
id varchar primary key,
"name"."name" varchar)
column_encoded_bytes=0;
--关于hbase 和 phoenix 表映射中数值类型的问题
(3)
--hbase 创建测试表 注意: 如果要插入数字类型,需要通过Bytes.toBytes(123456)来实现。 但是查询的时候 解码默认使用的格式转换器是toString
hbase(main):001:0> create 'person','info'
hbase(main):001:0> put 'person','1001', 'info:salary', Bytes.toBytes(123456)
get 'person','1001' --hbase 默认使用的格式转换器是toString
info:salary timestamp=1624878007597, value=\x00\x00\x00\x00\x00\x01\xE2@
--使用不同的格式转换器
--toInt
get 'person','1001',{COLUMNS => ['info:salary:toInt']}
info:salary timestamp=1624879072277, value=0
--toLong
get 'person','1001',{COLUMNS => ['info:salary:toLong']}
COLUMN CELL
info:salary timestamp=1624879072277, value=123456
--phoenix 创建表映射
create table "person"(
id varchar primary key,
"info"."salary" integer)
column_encoded_bytes=0;
select * from "person"
1001 | -2147483648
会发现数字显示有问题
--为什么?
Hbase中存储数值类型的值(如int,long等)会按照正常数字的补码进行存储. 而phoenix对数字的存储做了特殊的处理. phoenix 为了解决遇到正负数同时存在时,
导致负数排到了正数的后面(负数高位为1,正数高位为0,字典序0 < 1)的问题。 phoenix在存储数字时会对高位进行转换.原来为1,转换为0, 原来为0,转换为1.
因此,如果hbase表中的数据的写是由phoenix写入的,不会出现问题,因为对数字的编解码都是phoenix来负责。如果hbase表中的数据不是由phoenix写入的,数字的编码由hbase负责.
而phoenix读数据时要对数字进行解码。 因为编解码方式不一致。导致数字出错.
--3 解决办法: 在phoenix中创建表时使用无符号的数值类型. unsigned_long
create table "person"(id varchar primary key,"info"."salary" unsigned_long )
column_encoded_bytes=0;
Hbase API
--Phoenix 二级索引
--表结构 id是主键 主键默认带索引(就是row_key)
0: jdbc:phoenix:> select * from "fpx"."student";
+-------+------------+-----------+
| ID | NAME | ADDR |
+-------+------------+-----------+
| 1 | ava | zhijiang |
| 123 | wangbadan | beijing |
| 1234 | zhubajie | anhui |
+-------+------------+-----------+
--测试索引的作用
1.全局二级索引
Global Index是默认的索引格式,创建全局索引时,会在HBase中建立一张新表。也就是说索引数据和数据表是存放在不同的表中的,因此全局索引适用于多读少写的业务场景。
写数据的时候会消耗大量开销,因为索引表也要更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。
在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。
--1.创建索引
CREATE INDEX my_index ON my_table (my_col,my_col);
--给name字段创建索引
CREATE INDEX my_index1 ON "fpx"."student" (name);
--在 hbase 中出现的索引表的结构 索引列加入到了新表的row_key中
scan 'fpx:MY_INDEX1'
ROW COLUMN+CELL
ava\x001 column=0:_0, timestamp=1624885853671, value=x
wangbadan\x00123 column=0:_0, timestamp=1624885853671, value=x
zhubajie\x001234 column=0:_0, timestamp=1624885853671, value=x
--索引表起作用的情况
explain select id from "fpx"."student"; //FULL SCAN
explain select name from "fpx"."student" where id ='1'; //POINT LOOKUP
explain select name from "fpx"."student" where name ='ava'; //RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
explain select addr from "fpx"."student" where name ='ava'; //FULL SCAN
explain select id,name from "fpx"."student" where id ='1' ; //POINT LOOKUP ON
explain select id,name from "fpx"."student" where name ='ava' ; // RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
explain select id,name,addr from "fpx"."student" where id ='1' ; //POINT LOOKUP
explain select id,name,addr from "fpx"."student" where name='ava' ; //FULL SCAN
如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升
筛选条件是索引字段 并且查询字段都是索引字段 会使用索引表
单个字段的索引表中除了索引字段 没有其他字段,如果需要其他字段只能全部遍历表
索引主要是为了给筛选条件用
--创建复合索引
--删除原来的单列索引
drop index my_index1 on "fpx"."student";
--创建复合索引
CREATE INDEX my_index1 ON "fpx"."student" (name,addr);
--habse中出现的索引表的结构 将name和addr都合在一起作为row_key
scan 'fpx:MY_INDEX1'
ROW COLUMN+CELL
ava\x00zhijiang\x001 column=0:_0, timestamp=1624889860198, value=x
wangbadan\x00beijing\x00123 column=0:_0, timestamp=1624889860198, value=x
zhubajie\x00anhui\x001234 column=0:_0, timestamp=1624889860198, value=x
--索引表起总用的情况
explain select id,name from "fpx"."student" where name='ava' ; //RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
explain select id,name,addr from "fpx"."student" where id='1' ; //POINT LOOKUP ON 1 KEY
explain select id,name,addr from "fpx"."student" where name='ava' ; //RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
explain select id,name,addr from "fpx"."student" where name='ava' and id='1' ;//POINT LOOKUP ON
explain select id,name,addr from "fpx"."student" where name='ava' and addr ='zhijiang' ;//SCAN OVER fpx:MY_INDEX1 ['ava','zhijiang']
explain select id,name,addr from "fpx"."student" where addr ='zhijiang' ;//FULL SCAN OVER fpx:MY_INDEX1 --因为addr在索引表中不是打头的所以走不了索引
--2.创建携带其他字段的全局索引 索引包含
CREATE INDEX my_index ON my_table (v1) INCLUDE (v2);
--删除原来的复合索引
drop index my_index1 on "fpx"."student";
--创建索引包含其他字段
CREATE INDEX my_index1 ON "fpx"."student" (name) INCLUDE (addr);
--索引表的结构 设为索引的name 同一列会有addr字段 查询到name的时候是将addr的值带出来
ROW COLUMN+CELL
ava\x001 column=0:0:ADDR, timestamp=1624890638512, value=zhijiang
ava\x001 column=0:_0, timestamp=1624890638512, value=x
wangbadan\x00123 column=0:0:ADDR, timestamp=1624890638512, value=beijing
wangbadan\x00123 column=0:_0, timestamp=1624890638512, value=x
zhubajie\x001234 column=0:0:ADDR, timestamp=1624890638512, value=anhui
zhubajie\x001234 column=0:_0, timestamp=1624890638512, value=x
--起作用的情况
explain select id,name,addr from "fpx"."student" where name='ava' ; // RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
explain select id,name,addr from "fpx"."student" where name='ava' and addr ='zhijiang' ;//RANGE SCAN OVER fpx:MY_INDEX1 ['ava']
--本地二级索引
--删除原来的包含索引
drop index my_index1 on "fpx"."student";
Local Index适用于写操作频繁的场景。
索引数据和数据表的数据是存放在同一张表中(且是同一个Region),避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。
--创建本地索引
CREATE LOCAL INDEX my_index ON my_table (my_column);
CREATE LOCAL INDEX my_index1 ON "fpx"."student" (name);
--本地索引的结构 直接将索引创建在目标表上 不在额外创建索引表 所以使用索引查找的时候 可以将其他字段带出来
ROW COLUMN+CELL
\x00\x00ava\x001 column=L#0:_0, timestamp=1624884677997, value=_0
\x00\x00wangbadan\x00123 column=L#0:_0, timestamp=1624884632635, value=_0
\x00\x00zhubajie\x001234 column=L#0:_0, timestamp=1624884648318, value=_0
1 column=0:ADDR, timestamp=1624884677997, value=zhijiang
1 column=0:NAME, timestamp=1624884677997, value=ava
1 column=0:_0, timestamp=1624884677997, value=x
123 column=0:ADDR, timestamp=1624884632635, value=beijing
123 column=0:NAME, timestamp=1624884632635, value=wangbadan
123 column=0:_0, timestamp=1624884632635, value=x
1234 column=0:ADDR, timestamp=1624884648318, value=anhui
1234 column=0:NAME, timestamp=1624884648318, value=zhubajie
1234 column=0:_0, timestamp=1624884648318, value=x
explain select id,name from "fpx"."student" where name='ava' ; //RANGE SCAN OVER fpx:student [1,'ava']
explain select id,name,addr from "fpx"."student" where name='ava' ; // RANGE SCAN OVER fpx:student [1,'ava']
habse和Hive的集成
--Hbase与Hive的集成 负责存储数据的是Hbase 不是hive hive只是拿来用而已
--在hive上创建表和hbase相关 同时会在hbase中生成相关的表
CREATE TABLE hive_hbase_emp_table(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' --存储格式是Hbase的
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno") --列族里面的字段叫啥 只有一个列族
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table"); --hbase中生成的表叫啥
--这表妹法直接load进去数 没有符合hfile格式的文件 而且建表也妹指定分隔符
--无所谓的 搞个临时表 load进去数之后 再insert到目标表
CREATE TABLE hive_emp_temp2(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/hive-3.1.2/emp.txt' into table hive_emp_temp2;
insert into hive_hbase_emp_table select * from hive_emp_temp2;
--查看hbase中生成的相关表 hbase_emp_tabl 发现也同步插入数据了
7369 column=info:deptno, timestamp=1624928069131, value=20
7369 column=info:ename, timestamp=1624928069131, value=SMITH
7369 column=info:hiredate, timestamp=1624928069131, value=1980-12-17
7369 column=info:job, timestamp=1624928069131, value=CLERK
7369 column=info:mgr, timestamp=1624928069131, value=7902
7369 column=info:sal, timestamp=1624928069131, value=800.0
--创建外部表去使用Hbase的数据 简单来说 使用hive这个工具去分析Hbase的数 和上面一样 就多了个EXTERNAL
CREATE EXTERNAL TABLE relevance_hbase_emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" =
":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
--默认第一个字段为rowkey,即为id 就是:key
create external table tian(
id int,
name string, --0:name
age int, --0:age
score int -- 0:score
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" =
":key,0:name,0:age,0:score")
TBLPROPERTIES ("hbase.table.name" = "fpx:tian");
--对应的hbase表的数据
scan 'fpx:tian'
ROW COLUMN+CELL
1001 column=0:age, timestamp=1624938726055, value=18
1001 column=0:name, timestamp=1624938689031, value=xiaozhang
1002 column=0:name, timestamp=1624938697568, value=xiaosan
1003 column=0:name, timestamp=1624938708107, value=xiaosi
1003 column=0:score, timestamp=1624938737516, value=188
--查看hive的数据 按照最多的列族来 其他row_key没有的字段就是null
select * from tian;
OK
tian.id tian.name tian.age tian.score
1001 xiaozhang 18 NULL
1002 xiaosan NULL NULL
1003 xiaosi NULL 188
绝不摆烂