Cris 小哥哥的大数据项目之 Hive 统计 YouTube 热门视频

Author:Cris

文章目录

  • Cris 小哥哥的大数据项目之 Hive 统计 YouTube 热门视频
      • Author:Cris
    • 1. 项目需求
    • 2. 表结构和 ETL
      • 2.1 表结构
      • 2.2 ETL 原始数据
      • 2.3 开启 IDEA 完成 ETL 代码
        • - Mapper 阶段
        • - EtlStringUtil
        • - Driver
        • - 测试
    • 3. 服务器完成 ETL 和表建立
      • 3.1 打包和数据清理
      • 3.2 建表
      • 3.3 导入数据
      • 3.4 向 orc 表插入数据
    • 4. 实际业务分析
      • 4.1 统计视频观看数Top10
      • 4.2 统计视频类别热度Top10
      • 4.3 统计出视频观看数最高的20个视频的所属类别以及每个类别包含Top20视频的个数
      • 4.4 统计视频观看数Top50所关联视频的所属类别按照视频上传量排序
      • 4.5 统计每个类别中的视频热度Top10,以Music为例
      • 4.6 统计每个类别中视频流量Top10,以Music为例
      • 4.7 统计上传视频最多的用户Top10以及他们上传的观看次数在前20的视频
      • 4.8 统计每个类别视频观看数Top10

1. 项目需求

统计 YouTube 网站的常规指标,各种TopN指标:

–统计视频观看数Top10

–统计视频类别热度Top10

–统计视频观看数Top20所属类别

–统计视频观看数Top50所关联视频的所属类别Rank

–统计每个类别中的视频热度Top10

–统计每个类别中视频流量Top10

–统计上传视频最多的用户Top10以及他们上传的视频

–统计每个类别视频观看数Top10

2. 表结构和 ETL

2.1 表结构

  • 视频表
字段 备注 详细描述
video id 视频唯一id 11位字符串
uploader 视频上传者 上传视频的用户名String
age 视频年龄 视频在平台上的整数天
category 视频类别 上传视频指定的视频分类
length 视频长度 整形数字标识的视频长度
views 观看次数 视频被浏览的次数
rate 视频评分 满分5分
Ratings 流量 视频的流量,整型数字
conments 评论数 一个视频的整数评论数
related ids 相关视频id 相关视频的id,最多20个

其中 related ids 有可能为空(新上传的视频也来不及通过数据分析为其添加相关视频)

  • 用户表
字段 备注 字段类型
uploader 上传者用户名 string
videos 上传视频数 int
friends 朋友数量 int

2.2 ETL 原始数据

​ 通过观察原始数据形式,可以发现,视频可以有多个所属分类,每个所属分类用&符号分割,且分割的两边有空格字符,同时相关视频也是可以有多个元素,多个相关视频又用“\t”进行分割。为了分析数据时方便对存在多个子元素的数据进行操作,我们首先进行数据重组清洗操作。即:将所有的类别用“&”分割,同时去掉两边空格,多个相关视频id也使用“&”进行分割

原始数据示例如下:

第四列表示类别,需要 ETL 将空格去掉;然后是第十列数据表示关联的视频 id,同样需要 ETL 将 \t 分割符变为指定的分隔符

2.3 开启 IDEA 完成 ETL 代码

​ 写我们的 ETL 代码之前,需要明白数据清洗的目的,即需要将原数据按照怎么样的规则来进行清洗,这才是 ETL 的重点,只有清晰明了 原材料最终产品 之间的关系,才会很快速的完成 ETL 代码的编写

- Mapper 阶段

ETL 一般都是使用 Mapper 阶段来对我们的原始数据进行筛选,所以通常都是只有 Mapper 阶段,这一点需要注意!

/*** 进行 ETL 流程的 Mapper,不需要走 Reducer** @author zc-cris* @version 1.0**/
@SuppressWarnings("JavaDoc")
public class MovieTopMapper extends Mapper<LongWritable, Text, Text, NullWritable> {private Text k = new Text();/** 通过工具类将每行数据进行校验和转换* @param key 文本偏移量* @param value 每行文本* @param context MapReduce 上下文对象* @throws IOException* @throws InterruptedException*/@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {String[] strings = value.toString().split("\t");String result = EtlStringUtil.handle(strings);if (result != null) {// 自定义数据清洗成功的计数器并自增context.getCounter("ETLCounter", "true").increment(1);k.set(result);context.write(k, NullWritable.get());} else {// 自定义数据清洗失败并过滤的计数器并自增context.getCounter("ETLCounter", "false").increment(1);}}
}

- EtlStringUtil

根据上面的 Mapper 阶段代码,可以发现我们需要一个工具类来完成具体的数据校验和转换,代码如下:

/*** ETL 工具类** @author zc-cris* @version 1.0**/
public class EtlStringUtil {private static StringBuilder stringBuilder = new StringBuilder();private static final int STANDARD_LENGTH = 9;private static final int STANDARD_LENGTH_SUB_1 = 8;/*** 使用 main 方法做测试,保证工具类的可用性** @param args main 方法的参数*/public static void main(String[] args) {String handle = EtlStringUtil.handle("SDNkMu8ZT68\tw00dy911\t630\tPeople & Blogs\t186\t10181\t3.49\t494\tcris\tloveu\tsimida".split("\t"));System.out.println("handle = " + handle);}/*** 将输入的字符串数组转换为合格的数据** @param strings 待处理的字符串数组* @return  处理后的字符串*/static String handle(String[] strings) {// 一定要清除原 StringBuilder 对象的字符串内容!!!stringBuilder.delete(0, stringBuilder.length());if (strings.length < STANDARD_LENGTH) {return null;}strings[3] = strings[3].replaceAll(" ", "");if (strings.length == STANDARD_LENGTH) {for (int i = 0; i < STANDARD_LENGTH_SUB_1; i++) {stringBuilder.append(strings[i]).append("\t");}stringBuilder.append(strings[8]);} else {for (int i = 0; i < STANDARD_LENGTH; i++) {stringBuilder.append(strings[i]).append("\t");}for (int i = 9; i < strings.length - 1; i++) {stringBuilder.append(strings[i]).append("&");}stringBuilder.append(strings[strings.length - 1]);}return stringBuilder.toString();}
}

- Driver

最后就是整个 ETL 的驱动类,使用 Hive 官方推荐的方式来写?

/*** ETL 驱动类,最标准的写法** @author zc-cris* @version 1.0**/
@SuppressWarnings("JavaDoc")
public class MovieTopDriver implements Tool {/*** 抽象的配置类**/private Configuration configuration = new Configuration();/*** 抽象的任务类**/private Job job = null;public static void main(String[] args) {try {new MovieTopDriver().run(args);} catch (Exception e) {e.printStackTrace();}}@Overridepublic int run(String[] args) throws Exception {job = Job.getInstance(configuration);job.setJarByClass(MovieTopDriver.class);job.setMapperClass(MovieTopMapper.class);job.setNumReduceTasks(0);job.setOutputKeyClass(Text.class);job.setOutputValueClass(NullWritable.class);initFileInputPath(args[0]);initFileOutputPath(args[1]);boolean flag = job.waitForCompletion(true);return flag ? 0 : 1;}/*** 对 ETL 清理后的文件输出路径做校验** @param outputPath ETL 输出文件路径* @throws IOException*/private void initFileOutputPath(String outputPath) throws IOException {FileSystem fileSystem = FileSystem.get(configuration);Path path = new Path(outputPath);boolean exists = fileSystem.exists(path);if (exists) {// 删除已经存在的 ETL 文件清洗输出目录fileSystem.delete(path, true);}FileOutputFormat.setOutputPath(job, path);}/*** 对 ETL 待清理文件输入路径做出校验** @param inputPath ETL 输入文件路径* @throws IOException*/private void initFileInputPath(String inputPath) throws IOException {FileSystem fileSystem = FileSystem.get(configuration);Path f = new Path(inputPath);boolean exists = fileSystem.exists(f);if (exists) {FileInputFormat.setInputPaths(job, f);} else {throw new RuntimeException("ETL 文件输入路径不存在!!!");}}@Overridepublic void setConf(Configuration conf) {this.configuration = conf;}@Overridepublic Configuration getConf() {return this.configuration;}
}

- 测试

对我们写的任何代码,必须自己亲自测试一遍才可以提交!!!

工具类的测试代码已经写在上面的工具类里面,工具类没有问题,才能在本地测试数据的转换流程是否 ok

让我们的程序跑起来。。。

结果如下:

观察第四列和第十列的数据,可以发现我们已经成功完成了 ETL 需求?

3. 服务器完成 ETL 和表建立

之前在本地上,我们已经跑成功了 ETL,接下来打包我们的程序丢到 Linux 上对数据进行清洗,然后建立数据表

3.1 打包和数据清理

这里使用 Maven 打包程序

这里使用 rz 命令将数据和包发送到 Linux 上(速度有点慢,大文件不推荐使用 lrzsz 插件)

将原始数据上传到 HDFS 上

hadoop fs -put ./movie /movie

然后跑 ETL 程序

hadoop jar ./movieTop-1.0-SNAPSHOT.jar "com.cris.MovieTopDriver" /movie /movie_etl_out

3.2 建表

这里我们需要建立四张表,两张原始数据表(直接和 ETL 后的数据建立对应关系),还有两外两张表映射经过压缩后的 orc 格式的文件,我们实际查询使用的表都是 orc 格式的数据,这样子查询效率高多了,而且压缩后的文件也很小~

  • 建表

    # 原始数据表
    create table movieTop_ori(videoId string, uploader string, age int, category array<string>, length int, views int, rate float, ratings int, comments int,relatedId array<string>)
    row format delimited
    fields terminated by "\t"
    collection items terminated by "&"
    stored as textfile;# 原始用户数据表
    create table movieTop_user_ori(uploader string,videos int,friends int)
    row format delimited
    fields terminated by "\t"
    stored as textfile;# 创建 orc 压缩表
    create table movieTop_orc(videoId string, uploader string, age int, category array<string>, length int, views int, rate float, ratings int, comments int,relatedId array<string>)
    row format delimited fields terminated by "\t"
    collection items terminated by "&"
    stored as orc;create table movieTop_user_orc(uploader string,videos int,friends int)
    row format delimited
    fields terminated by "\t"
    stored as orc;
    

3.3 导入数据

首先导入 ETL 后的数据

load data inpath "/movie_etl_out" into table movieTop_ori;

load data inpath "/user.txt" into table movieTop_user_ori;

3.4 向 orc 表插入数据

insert into table movieTop_orc select * from movieTop_ori;

insert into table movieTop_user_orc select * from movieTop_user_ori;

4. 实际业务分析

4.1 统计视频观看数Top10

思路:使用order by按照views字段做一个全局排序即可,同时我们设置只显示前10条

select videoId, views from movieTop_orc order by views desc limit 10;

4.2 统计视频类别热度Top10

思路:

  1. 即统计每个类别有多少个视频,显示出包含视频最多的前10个类别。
  2. 我们需要按照类别group by聚合,然后count组内的videoId个数即可。
  3. 因为当前表结构为:一个视频对应一个或多个类别。所以如果要group by类别,需要先将类别进行列转行(展开),然后再进行count即可。
  4. 最后按照热度排序,显示前10条
  • 第一步将每个 video 的类别标签爆炸开来,生成临时的一个标签对应一个 video 的表
# LATERAL VIEW udtf(expression) tableAlias AS columnAlias
select videoId,category_name from movieTop_orc lateral view explode(category) category_info as category_name;
  • 根据临时表进行热度最高的类别 top 10 查询
select count(videoId) as hot, category_name from
(select videoId, category_name from movieTop_orc lateral view explode(category) category_info as category_name
) as tbl_temp1
group by category_name
order by hot desc
limit 10;

4.3 统计出视频观看数最高的20个视频的所属类别以及每个类别包含Top20视频的个数

思路:

  1. 先找到观看数最高的20个视频所属条目的所有信息,降序排列

  2. 把这20条信息中的category分裂出来(列转行)

  3. 最后查询视频分类名称和该分类下有多少个Top20的视频

order by 和 group by 字句一样,字段都必须在 select 字句中出现!!!

牢记 lateral view explode(字段)tableAlias as clounmnAlias 语法~~~

select videoId, category,views from movieTop_orc order by views desc limit 20;
select videoId, category_name from (select videoId, category from movieTop_orc order by views desc limit 20
) as tbl_temp lateral view explode(category) category_info as category_name;
select count(videoId) as video_count, category_name from (select videoId, category_name from (select videoId, category, views from movieTop_orc order by views desc limit 20
) as tbl_temp lateral view explode(category) category_info as category_name
) as tbl_temp2 group by category_name order by video_count desc;

4.4 统计视频观看数Top50所关联视频的所属类别按照视频上传量排序

  1. 先要查询出观看数前 50 的视频信息(关联视频是重点!)
select views, relatedId from movieTop_orc order by views desc limit 50;
  1. 关联视频字段是 array 数据类型,需要 explode
select views, related_info from t1 lateral view explode(relatedId) related_numbers as related_info;
  1. 求出这些关联视频的所属类别,需要 join 原始的 movieTop 表
select  distinct(t2.related_info),tbl_ori.category, t2.views from t2 join movieTop_orc as tbl_ori on tbl_ori.videoId = t2.related_info;
  1. 因为所属类别也是 array 数据类型,也需要 explode
select category_name, views, related_info from t3 lateral view explode(category) category_info as category_name;
  1. 对这些类别排序
select category_name, count(related_info) as hot from t4 group by category_name order by hot desc;
  1. 整合所有 sql
select category_name, count(related_info) as hot from
(select category_name, views, related_info from (select  distinct(t2.related_info),tbl_ori.category, t2.views from ( select views, related_info from (select views, relatedId from movieTop_orc order by views desc limit 50)as t1 lateral view explode(relatedId) related_numbers as related_info) as t2 join movieTop_orc as tbl_ori on tbl_ori.videoId = t2.related_info) as t3 lateral view explode(category) category_info as category_name) as t4
group by category_name order by hot desc;

4.5 统计每个类别中的视频热度Top10,以Music为例

  1. 要想统计Music类别中的视频热度Top10,需要先找到Music类别,那么就需要将category展开,所以可以创建一张表用于存放categoryId展开的数据。
  2. 向category展开的表中插入数据。
  3. 统计对应类别(Music)中的视频热度

Tips:遇上有多个标签的字段(通常是 array 数据类型,例如分类信息等),通常需要建立一张关于每个标签对应每条数据的表,这样子有利于做关于标签的复杂 sql 查询

create table movieTop_category(videoId string, uploader string, age int, categoryId string, length int, views int, rate float, ratings int, comments int, relatedId array<string>)
row format delimited
fields terminated by "\t"
collection items terminated by "&"
stored as orc;
insert into table movieTop_categoryselect videoId,uploader,age,categoryId,length,views,rate,ratings,comments,relatedId from movieTop_orc lateral view explode(category) category_tbl as categoryId;

最后执行查询语句

select videoId, views from movieTop_category where categoryId = 'Music' order by views desc limit 10;

4.6 统计每个类别中视频流量Top10,以Music为例

select videoId, ratings from movieTop_category where categoryId = 'Music' order by ratings desc limit 10;

4.7 统计上传视频最多的用户Top10以及他们上传的观看次数在前20的视频

select t2.videoId, t2.views, t1.uploader from
(select uploader,videos from movieTop_user_orc order by videos desc limit 10) as t1
join movieTop_orc as t2 on
t1.uploader = t2.uploader
order by t2.views desc limit 20;

4.8 统计每个类别视频观看数Top10

Tips: 这种分类别统计 TopN 的要求一般都是使用 rank 函数搭配 over 开窗函数

  1. 先得到categoryId展开的表数据

  2. 子查询按照categoryId进行分区,然后分区内排序,并生成递增数字,该递增数字这一列起名为rank列

  3. 通过子查询产生的临时表,查询 rank 值小于等于 10 的数据行即可

select * from
(select videoId, views, categoryId, row_number() over(partition by categoryId order by views desc) as rk from movieTop_category) as t1
where t1.rk < 11;

每个类别排序和根据指定的类别排名是不一样的,前者需要 rank 函数搭配 over 开窗函数,后者仅仅 order by 搭配 where 字句即可

这里没有滚动截屏,所以没有展示所有类别的排名,需悉知!

Cris 小哥哥的大数据项目之 Hive 统计 YouTube 热门视频相关推荐

  1. Cris 小哥哥的大数据项目之 HBase 模拟微博核心功能

    Cris 小哥哥的大数据项目之 HBase 模拟微博核心功能 Author:Cris 文章目录 Cris 小哥哥的大数据项目之 HBase 模拟微博核心功能 Author:Cris 0. 序 1. 需 ...

  2. 大数据技术之Hive实战——Youtube项目(二)

    三.项目 原始数据youtube在此下载:https://pan.baidu.com/s/1we1KPA2IIEAGIJczyr2dMQ 3.1.数据结构 3.1.1.视频表  这里写图片描述 这里写 ...

  3. 多数大数据项目都以失败而告终的原因

    多数大数据项目都以失败而告终的原因 摘要:核心提示:几乎每个人的心目中,大数据就是企业IT部门的大大小小的结构化和非结构化数据,而且其量正在成倍的增长. [...] 核心提示:几乎每个人的心目中,大数 ...

  4. 运维专家:我在大数据项目中踩过的那些坑

    一.主要讨论人员 提问:陈超,七牛云技术总监 回答:朱冠胤,百度资深大数据专家,连续两次百度最高奖得主. 二.引言 "坐而论道"是一个轮流问答的玩法.本文是大数据主题周中,几位国内 ...

  5. 大数据项目交付国标_在紧迫的期限内交付大型项目

    大数据项目交付国标 by Paul McGillivray 保罗·麦吉里夫瑞(Paul McGillivray) 在紧迫的期限内交付大型Web项目 (Delivering a big web proj ...

  6. 为IoT和大数据项目分配IT资源

    大数据和物联网项目给IT基础架构带来了前所未有的压力. Internet of Things(IoT) 和大数据应用已经给网络和存储架构带来了压力,更不用说这还需要IT专家使用不同的技能和工具来管理这 ...

  7. 助力工业物联网,工业大数据项目介绍及环境构建【一、二】

    文章目录 工业大数据项目介绍及环境构建 01:专栏目标 02:项目背景 03:项目需求 04:业务流程 05:技术选型 06:Docker的介绍 07:Docker的网络 08:Docker的使用 0 ...

  8. 大数据项目离线数仓(全 )二(数仓系统)

    本文仅仅包含数据仓库系统的搭建,其他内容请关注我的博客!在<项目>专栏里!!! 本篇文章参考尚硅谷大数据项目写成! 目录 一.数据仓库系统 1.1基础概念 1.1.1数据分层的好处 1.1 ...

  9. 51GIS学院|分享大数据项目架构思考(一)

    大数据概念到今天,炒作的最高风口已经过去了,根据Gartent发布的HypeCycle曲线,大数据已经处于炒作顶点之后的衰退期. HypeCycle曲线 而从HypeCycle曲线定义的阶段来看,越过 ...

最新文章

  1. Python3中__call__方法介绍
  2. python高阶函数(abs()、round()、map()、reduce()、filter())
  3. linux 卡在grub_安装Linux系统,Ubuntu时卡在这个界面不动了,有3个小时了。。显示:“正在运行update_grub”......
  4. 传感器数据完善 AI 功能,激起机器人“网络效应”
  5. 《游戏脚本的设计与开发》-第一部分总结 文字脚本的功能扩展和一个游戏测试...
  6. Linux0.00 代码解析(二)
  7. Jmeter脚本增强之参数化(多方式实现)(6)
  8. php mysql 拖拉 报表_php+mysql 生成统计报表
  9. Windows XP 按权限设置共享
  10. java 怎么做批量修改_JAVA实现批量修改文件名称
  11. 周记——20151123
  12. 文本挖掘与matlab,文本挖掘与数据挖掘:发现差异
  13. Java-HelloWorld
  14. 让my97 datepicker兼容ie9、ie10、ie11
  15. [附源码]计算机毕业设计Python架构的博客平台设计(程序+源码+LW文档)
  16. 大众点评列表页采集思路,破解字体文件反爬(包含项目github 可用时间至2020-01-21)
  17. 超牛逼!这款开源性能监控系统真强大~
  18. 工业物联网RTU与DTU的区别
  19. HUSTPC2022
  20. 2014年4月份第4周51Aspx源码发布详情

热门文章

  1. 基于诱捕器图像的飞蛾害虫自动检测
  2. 给笔记本换电池18650锂电池\电池损耗
  3. 北师大版图形的旋转二教案_北师大版数学六年级下册《图形的旋转(二)》教案疲惫不堪的意思...
  4. 基于三菱PLC和MCGS组态农田智能灌溉系统
  5. 1. 医院的就诊流程是怎样的?
  6. php修改文件临时目录,PHP_详谈PHP文件目录基础操作,我们知道,临时声明的变量是 - phpStudy...
  7. 营收大增成Q2财报关键词,飞轮效应成达达集团业绩增长驱动力
  8. PHP语言入门难吗 需要学习哪些东西
  9. 小程序自定义头部导航栏(“navigationStyle“: “custom“),自定义tabBar
  10. OpenStack 2014 用户调查解析——中国部署规模仅次于美国