前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hive DML应用

Hive DML应用

原创
作者头像
esse LL
修改2024-04-03 07:54:50
2230
修改2024-04-03 07:54:50
举报
文章被收录于专栏:操作系统实验

Hive DML语法包括select、insert、update和delete等操作

Hive从0.14版本开始支持事务和ACID(原子性、一致性、隔离性、持久性)特性,从而支持update和delete操作

1.准备数据

生成模拟数据可以使用python脚本或者mysql存储过程,为了降低难度此处使用python3脚本

代码语言:bash
复制
vi gensamples.py # 输入下面的python脚本
代码语言:python
代码运行次数:0
复制
import csv  
import random  
from datetime import datetime, timedelta
  
# 可以自由定义歌曲名称的抽样范围  
song_names = (  
    "喜羊羊", "沸羊羊", "小狗", "小猪", "小猫",  
)  
  
# 生成样本数据的函数  
def generate_sample_data(num_rows):  
      
    data = []  
    start_date = datetime(2023, 1, 1)  
    end_date = datetime(2023, 12, 31)  
    delta = (end_date - start_date).days + 1  # 计算两个日期之间的天数差,并加1以包含结束日期  
      
    for _ in range(num_rows):  
        # 从歌曲名称元组中随机抽单个样本  
        song_name = random.choice(song_names)  
        # 随机播放量  
        plays = random.randint(1, 10000)  
        # 生成目标范围内的随机日期  
        random_date = start_date + timedelta(days=random.randint(0, delta - 1))  
        date = random_date.strftime('%Y-%m-%d')  
        # 新增一行数据  
        data.append([song_name, plays, date])  
    return data  
  
# 生成10000行样本数据  
sample_data = generate_sample_data(10000)  
    
# 将数据写入csv文件,不使用表头  
with open('play_data.csv', 'w', newline='', encoding='utf-8') as csvfile:  
    writer = csv.writer(csvfile)  
    # 使用逗号分隔的简单格式  
    for row in sample_data:  
        writer.writerow(row)  
    
print("可以使用vi play_data.csv查看生成的数据文件")  
代码语言:bash
复制
python gensamples.py
代码语言:bash
复制
head -n 10 play_data.csv
cp play_data.csv /tmp/

确认过数据文件后,之后可以在Hive中加载该数据文件

2.建表并导入数据

建一个普通表用于导入数据文件,然后事务表用于支持数据更新操作:

代码语言:sql
复制
create database if not exists z3music;
use z3music;
create table play_data (
    song_name string, plays int, p_date date
) row format delimited fields terminated by ',';
代码语言:sql
复制
load data local inpath '/tmp/play_data.csv' into table play_data;
代码语言:sql
复制
use z3music;
create table play_data_ttb (
    song_name string, plays bigint, p_date date, daily_rank int
) 
clustered by (p_date) into 8 buckets
stored as orc 
tblproperties ('transactional'='true');

因为随机生成的数据会有重复,导入数据的时候顺便处理一下:

代码语言:sql
复制
insert into play_data_ttb 
select song_name,sum(plays),p_date, -1
from play_data
group by song_name, p_date;

这样就得到了这些歌曲在某些日期的播放次数了,但是排名现在还空着,没有计算出来,暂时填为-1

参考效果:

3.更新数据

play_data_ttb现在已经导入了数据,但是排名还没有更新,尝试使用update来得到更新这些歌曲在每日的排名:

代码语言:sql
复制
update play_data_ttb
set daily_rank = rank() over (partition by p_date order by plays desc)  

查看前20行数据,排名已经全部更新上了:

代码语言:sql
复制
select * from  play_data_ttb limit 20;

参考效果:

4.归档数据

尝试建一个归档表来存储某些低播放量的歌曲,并将它们从主表中删除

代码语言:sql
复制
create table archived_play_data like play_data_ttb;

将播放量低的数据导入到归档表:

代码语言:sql
复制
insert into table archived_play_data
select * from play_data_ttb
where plays < 1000;
代码语言:sql
复制
select * from archived_play_data limit 20;

播放量较低的情况比较少,只查出来六行数据:

从主表中删除这些数据:

代码语言:sql
复制
delete from play_data_ttb
where plays < 1000;

补充练习:使用存储过程生成模拟数据

在mysql中使用SQL语法查询更方便,所以可以尝试在mysql中生成10000行数据进行查询和分析

在mysql中定义play_data表存储数据:

代码语言:sql
复制
create database if not exists z3music;
use z3music;
create table play_data (
    song_name varchar(255), plays int, p_date date
);

定义song_names表作为抽样的范围:

代码语言:sql
复制
create table song_names (
    name varchar(255) not null
);
insert into song_names values ("喜羊羊"),("沸羊羊"),("小狗"),("小猪"),("小猫");

定义存储过程:

代码语言:sql
复制
delimiter //
create procedure insert_random_sample_data()
begin
    declare i int default 1;
    declare plays int;
    declare date_value date;
    declare song_name varchar(255);
    declare done int default false;
    declare cur cursor for select name from song_names;
    declare continue handler for not found set done = true;

    open cur;

    while i <= 10000 and not done do
        fetch cur into song_name;
        
        -- 如果游标结束的话重新打开并重置
        if done then
            close cur;
            set done = false;
            open cur;
        end if;
        
        -- 生成随机播放量
        set plays = floor(1 + (rand() * 10000));
        
        set date_value = date_add('2023-01-01', interval floor(rand() * (datediff('2023-12-31', '2023-01-01') + 1)) day);
        
        -- 插入数据到play_data表
        insert into play_data (song_name, plays, p_date) values (song_name, plays, date_value);
        
        -- 更新循环计数器
        set i = i + 1;
    end while;

    close cur;
end //
delimiter ;

调用存储过程,在play_data表中生成10000行模拟数据:

代码语言:sql
复制
call insert_random_sample_data();

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.准备数据
  • 2.建表并导入数据
  • 3.更新数据
  • 4.归档数据
  • 补充练习:使用存储过程生成模拟数据
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档