代码拉取完成,页面将自动刷新
1. 思考: 实现一个文章访问量的排行榜
使用redis存储数据需要分析的问题:
1. 使用哪种类型? zset
2. key: article:visit:top10
3. value: score(访问量) - member(文章标题)
4. 写入命令/API: zadd??? zincrby
zincrby article:visit:top10 1 Java
zincrby article:visit:top10 1 Bigdata
5. 读取命令/API: ZREVRANGE article:visit:top10 0 9 withscores
6. 是否过期:
2. 思考: 现有N个 User 对象,在Redis中如何存?
class User{
private String id ;
private String name ;
private Integer age ;
}
new User("1001" , "zhangsan" , 20)
new User("1002" , "lisi" , 25)
new User("1003" , "wangwu" , 22)
.....
方案一: 一个User对象存成一个String类型的kv
1. 使用哪种类型? string
2. key: user:1001
3. value: {"id":"1001", "name":"zhangsan", "age":20}
4. 写入命令/API: set
5. 读取命令/API: get
6. 是否过期:
方案二:一个User对象的每个属性都存成一个String类型的kv
1. 使用哪种类型? string
2. key: user:1001:id user:1001:name user:1001:age
3. value: 1001 zhangsan 20
4. 写入命令/API: set
5. 读取命令/API: get
6. 是否过期:
方案三: 一个User对象存成一个hash
1. 使用哪种类型? hash
2. key: user:1001
3. value: hash[id=1001, name=zhangsan,age=20]
4. 写入命令/API: hset
5. 读取命令/API: hget hgetall
6. 是否过期:
3. HBase shell namespace ddl
1) 查看所有的namespace
list_namespace
2) 查看namespace下的表
list_namespace_tables 'hbase'
3) 创建namespace
create_namespace 'mydb1'
create_namespace 'mydb2' , {'createtime'=>'2022-06-22' ,'author'=>'atguigu'}
4) 查看namespace的详情
describe_namespace 'mydb1'
5) 修改namespace
alter_namespace 'mydb2' , {METHOD=>'set' , 'author'=>'wyh','a'=>'a'}
alter_namespace 'mydb2' , {METHOD=>'unset' , NAME=>'a'}
6) 删除namespace
drop_namespace 'mydb1'
4. HBase shell table ddl
1) 查看所有的表
list
2) 创建表
create 'test1' , {NAME=>'info1' , VERSIONS=>3},{NAME=>'info2'}
create 'test2' , 'info1' , 'info2'
3) 查看表的详情
describe 'test1'
desc 'test1'
4) 修改表
alter 'test1' ,{NAME=>'info1',VERSIONS=>5} , {NAME=>'info3',VERSIONS=>2}
alter 'test1' , NAME=>'info1' , METHOD=>'delete'
alter 'test1' , 'delete'=>'info2'
5) 禁用/启用表
is_disabled 'test1'
is_enabled 'test1'
disable 'test1'
enable 'test1'
6) 删除表
disable 'test1'
drop 'test1'
7) 表是否存在
exists 'test2'
8) 查看表的region
list_regions 'test2'
4. HBase shell table dml
1) 创建表
create 'stu' , 'info1' , 'info2'
2) 插入数据/修改数据
put 'stu' , '1001' , 'info1:name' , 'zhangsan'
put 'stu' , '1001' , 'info1:age' , 25
put 'stu' , '1001' , 'info2:sex' , 'man'
put 'stu' , '1002' , 'info1:username' , 'lisi'
put 'stu' , '1002' , 'info1:userage' , 30
put 'stu' , '1002' , 'info2:gender' , 'women'
put 'stu' , '1002' , 'info2:address' , 'beijing'
put 'stu' , '1003' , 'info1:name' , 'wangwu'
put 'stu' , '1003' , 'info1:age' , 33
put 'stu' , '1003' , 'info2:sex' , 'man'
put 'stu' , '1004' , 'info1:name' , 'zhaoliu'
put 'stu' , '1004' , 'info1:age' , 35
put 'stu' , '1004' , 'info2:sex' , 'women'
put 'stu' , '10021' , 'info1:name' , 'xiaohua'
put 'stu' , '10021' , 'info1:age' , 18
put 'stu' , '10021' , 'info2:sex' , 'women'
3) 查询数据
get 'stu' , '1001'
get 'stu' , '1001' , 'info1'
get 'stu' , '1001' , 'info1:name'
4) 扫描数据
scan 'stu'
scan 'stu' , {STARTROW=>'1001' , STOPROW=>'1002!'}
5) 删除数据
delete 'stu' ,'1001' , 'info1:name' 删除某个版本的数据,默认最新版本.(Delete)
deleteall 'stu' , '1002' , 'info1:username' 删除某个列所有版本的数据(DeleteColumn)
deleteall 'stu' , '1003' 删除列族的数据(DeleteFamily)
6) 统计数据
count 'stu'
7) 清空表数据
truncate 'stu'
5. rowkey设计 + 预分区
1) 数据
user date pay
zhangsanfeng 2021-12-22 09:08:00 100
zhangsan 2022-01-05 09:08:00 100
zhangsan 2021-12-01 09:08:00 150
zhangsan 2021-12-30 09:08:00 100
zhangsanfeng 2022-01-04 09:08:00 200
lisi 2021-12-31 09:08:00 150
zhangsanfeng 2021-12-04 09:08:00 300
2) 需求一: 统计张三(某个人)在2021年12月份消费的总金额
rowkey: user_date
create 'test1' , 'info'
put 'test1' , 'zhangsanfeng_2021-12-22 09:08:00' , 'info:pay' , 100
put 'test1' , 'zhangsan_2022-01-05 09:08:00' , 'info:pay' , 100
put 'test1' , 'zhangsan_2021-12-01 09:08:00' , 'info:pay' , 150
put 'test1' , 'zhangsan_2021-12-30 09:08:00' , 'info:pay' , 100
put 'test1' , 'zhangsanfeng_2022-01-04 09:08:00' , 'info:pay' , 200
put 'test1' , 'lisi_2021-12-31 09:08:00' , 'info:pay' , 150
put 'test1' , 'zhangsanfeng_2021-12-04 09:08:00' , 'info:pay' , 300
scan 'test1' , {STARTROW=>'zhangsan_2021-12' , STOPROW=>'zhangsan_2021-12|'}
3) 需求二: 统计所有人在2021年12月份消费的总金额
rowkey: date(yyyy-MM)_user_date(-dd HH:mm:ss)
create 'test2' , 'info'
put 'test2' , '2021-12_zhangsanfeng_-22 09:08:00' , 'info:pay' , 100
put 'test2' , '2022-01_zhangsan_-05 09:08:00' , 'info:pay' , 100
put 'test2' , '2021-12_zhangsan_-01 09:08:00' , 'info:pay' , 150
put 'test2' , '2021-12_zhangsan_-30 09:08:00' , 'info:pay' , 100
put 'test2' , '2022-01_zhangsanfeng_-04 09:08:00' , 'info:pay' , 200
put 'test2' , '2021-12_lisi_-31 09:08:00' , 'info:pay' , 150
put 'test2' , '2021-12_zhangsanfeng_-04 09:08:00' , 'info:pay' , 300
需求二: scan 'test2', {STARTROW=>'2021-12' , STOPROW=>'2021-12|'}
需求一: scan 'test2', {STARTROW=>'2021-12_zhangsan' , STOPROW=>'2021-12_zhangsan_|'}
4) 预分区(方案一)
120个分区
-∞ ~ 001
001 ~ 002
002 ~ 003
.......
119 ~ 120
将某个人某月份的数据存在一个分区中
计算分区号: hash[user-date(yyyy-MM)] % 120 = 000 ~ 119
rowkey : 分区号_date(yyyy-MM)_user_date(-dd HH:mm:ss)
对于需求一没有任何问题,但是对于需求二来说,可能要扫描所有的分区,不太好.
5) 预分区(方案二)
120个分区
000 - 009 号分区存储1月份数据
...
110 - 119 号分区存储12月份数据
将120个分区平均分成12份, 每份10个分区,用来维护某个月份的数据.
计算分区号: hash[user] % 10 + 月份对应的分区开始值 = 分区号
rowkey: 分区号_date(yyyy-MM)_user_date(-dd HH:mm:SS)
6. schema
1) 创建schema
create schema if not exists mydb ;
create schema if not exists "mydb1";
2) 注意:
在Phoenix中写的schema名、表名、字段名等在Hbase中会默认转成大写形式.
如果希望保持小写,需要在phoenix中通过""引起来。
3) 切换schema
use mydb;
3) 删除schema
drop schema if exists "mydb1";
7. table
1) 查看表
!tables
2) 创建表(必须要指定主键,对应Hbase表的rowkey)
create table emp(
id varchar(10) primary key,
name varchar(20) ,
addr varchar(20)
);
3) 插入数据
upsert into emp (id ,name, addr) values('1001', 'zhangsan' , 'beijing');
4) 查询数据
select * from emp ;
select id ,name, addr from emp ;
5) 删除数据
delete from emp where id = '1001' ;
6) 删除表
drop table emp ;
8. 几个问题
1) 列编码问题
drop table emp ;
create table emp(
id varchar(10) primary key,
name varchar(20) ,
addr varchar(20)
)
COLUMN_ENCODED_BYTES = NONE;
upsert into emp (id ,name, addr) values('1001', 'zhangsan' , 'beijing');
2) value=x问题
upsert into emp (id ,name, addr) values('1002', null , null);
3) 数值问题
drop table user ;
create table user(
id varchar(10) primary key,
name varchar(20) ,
salary bigint
)
COLUMN_ENCODED_BYTES = NONE;
upsert into user (id ,name , salary ) values ('1001' , 'zhangsan' ,12345) ;
scan 'USER' , {COLUMNS => ['0:SALARY:toLong']}
put 'USER' , '1002' , '0:NAME' , 'lisi'
put 'USER' , '1002' , '0:SALARY' , Bytes.toBytes(45678)
注意: 将来如果要存储数值,可以使用无符号类型。
或者注意使用方式: 使用phoenix存,就使用phoenix查。 使用hbase存,就使用hbase查.
9. 二级索引 - 全局二级索引
0) 所谓的全局二级索引,实际上就是将索引列与原表的rowkey拼接起来充当成索引表的rowkey。
1) 准备一个表
create table user(
id varchar(20) primary key ,
name varchar(20) ,
addr varchar(20)
)
COLUMN_ENCODED_BYTES = NONE ;
2) 测试数据
upsert into user values('1001', 'zhangsan' , 'beijing');
upsert into user values('1002', 'lisi' , 'shanghai');
3) 几个测试
explain select * from user ; //FULL SCAN OVER USER
explain select * from user where id = '1001' ; //POINT LOOKUP ON 1 KEY OVER USER
explain select * from user where name = 'zhangsan' ; //FULL SCAN OVER USER
4) 创建索引
create index idx_user_name on user(name);
explain select * from user where name = 'zhangsan' ; //FULL SCAN OVER USER
explain select id, name from user where name = 'zhangsan' ; // RANGE SCAN OVER IDX_USER_NAME ['zhangsan']
5) 如果要查询非索引列的数据怎么办?
explain select * from user where name = 'zhangsan' ; //FULL SCAN OVER USER
explain select id ,name , addr from user where name = 'zhangsan' ; //FULL SCAN OVER USER
方案一: 给非索引列建索引(复合索引)
drop index idx_user_name on user ;
create index idx_user_name_addr on user(name , addr );
explain select * from user where name = 'zhangsan' ; //RANGE SCAN OVER IDX_USER_NAME_ADDR ['zhangsan']
方案二: 包含索引
drop index idx_user_name_addr on user ;
create index idx_user_name_include_addr on user(name) include (addr);
explain select * from user where name = 'zhangsan' ; //RANGE SCAN OVER IDX_USER_NAME_INCLUDE_ADDR ['zhangsan']
方案三: 本地二级索引
10. 二级索引 - 本地二级索引
1) 所谓的本地二级索引,实际上就是将索引列与原表的rowkey拼接,充当原表的rowkey.
drop index idx_user_name_include_addr on user ;
create local index idx_user_name on user (name) ;
explain select * from user where name = 'zhangsan' ; // RANGE SCAN OVER USER [1,'zhangsan']
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。