目录
1.数据准备
2.安装sqoop
3.使用sqoop将mysql中数据抽到hive
4.求每个区域点击Top3的产品
1.1产品信息表,存放在msyql关系型数据库
sql脚本百度网盘链接:
链接:https://pan.baidu.com/s/1dT8Rt2L49VMoi6OY3qCE2g
提取码:bhbx
1.2城市信息表,存放在mysql关系型数据库
sql脚本百度网盘链接:
链接:https://pan.baidu.com/s/1jJHVWTAMDMkpBNndCQxTUQ
提取码:jh2i
1.3用户点击行为信息表,生产中是是日志数据(页面埋点得到),存放在hdfs,为hive表
用户点击日志数据网盘链接:
链接:https://pan.baidu.com/s/1wFXTcQL-_wXEKQT1PM-c3g
提取码:b31w
#创建hive表,并加载数据
create table user_click(
user_id int,
session_id string,
action_time string,
city_id int,
product_id int
) partitioned by (day string)
row format delimited fields terminated by ',';
load data local inpath '/home/hadoop/data/topn/user_click.txt' overwrite into table user_click partition(day='2016-05-05');
2.1sqoop简介
一个将关系型数据库中的数据高效导入hadoop生态圈的工具。是apache的顶级项目。生产中更倾向使用的Sqoop1的相关版本,sqoop2版本并不好用,与sqoop1不兼容,不适用于生产部署。
本质是MR的作业。
2.2下载
我安装的是CDH5.7.0系列的软件,故我下载的是sqoop-1.4.6-cdh5.7.0.tar.gz版本
下载地址:http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.7.0.tar.gz
2.3解压安装
tar -zxvf sqoop-1.4.6-cdh5.7.0.tar.gz -C ~/app/
2.4拷贝mysql驱动jar包
cd ~/app/sqoop-1.4.6-cdh5.7.0/
cp ~/app/hive-1.1.0-cdh5.7.0/lib/mysql-connector-java-5.1.25.jar ~/app/sqoop-1.4.6-cdh5.7.0/lib/
2.5修改配置文件
cp conf/sqoop-env-template.sh conf/sqoop-env.sh #复制一份配置文件
vim conf/sqoop-env.sh #修改或追加,hadoop和hive的安装目录配置
export HADOOP_COMMON_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.7.0
export HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.7.0
export HIVE_HOME=/home/hadoop/app/hive-1.1.0-cdh5.7.0
2.6添加环境变量
vim ~/.bash_profile #添加如下环境变量
export SQOOP_HOME=/home/hadoop/app/sqoop-1.4.6-cdh5.7.0
export PATH=$SQOOP_HOME/bin:$PATH
source ~/.bash_profile #使环境变量生效
sqoop help #查看sqoop的命令帮助
扩展1:sqoop上的导入(import)指的是外部数据导入到Hadoop生态圈,导出(export)是将Hadoop生态圈上的数据导出到外部。
3.1 查看sqoop的命令使用帮助
sqoop help
sqoop import --help #查看数据导入的命令帮助
3.2 hive创建相应的表
create table city_info(
city_id int,
city_name string,
area string
)row format delimited fields terminated by '\t';
create table product_info(
product_id int,
product_name string,
extend_info string
)row format delimited fields terminated by '\t';
扩展2:生产上,sqoop数据导入时,hive上的表最好是手动创建的,不然可能会有各种问题。
3.3使用sqoop命令将mysql数据导入hive表中
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root --password 123456 \
--delete-target-dir \
--table city_info \
--hive-import \
--hive-table hive.city_info \
--hive-overwrite \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
--split-by city_id \
-m 2
我这里报异常信息:Exception in thread "main" java.lang.NoClassDefFoundError: org/json/JSONObject ,确实是少了对应的json 的 jar包,去http://www.java2s.com/Code/Jar/j/Downloadjavajsonjar.htm下载对应jar包,放到lib目录。
再次执行后报异常信息:ERROR hive.HiveConfig: Could not load org.apache.hadoop.hive.conf.HiveConf. Make sure HIVE_CONF_DIR is set correctly,显示是缺少了hive的jar包,复制hive的执行jar包到lib下。
cp ~/app/hive-1.1.0-cdh5.7.0/lib/hive-exec-1.1.0-cdh5.7.0.jar ~/app/sqoop-1.4.6-cdh5.7.0/lib/
再次执行加载数据语句,数据成功从mysql加载到hive。
#执行加载产品表sqoop命令
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root --password 123456 \
--delete-target-dir \
--table product_info \
--hive-import \
--hive-table hive.product_info \
--hive-overwrite \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
--split-by product_id \
-m 2
#检查hive上的数据目录,发现有两个文件
hdfs dfs -ls /user/hive/warehouse/hive/city_info
扩展3:由于sqoop在map任务前数据的分割与导出表主键相关,若导出表无主键,则必须指定数据分割的字段,这里指定的--split-by city_id,。
扩展4:sqoop只有MAP操作,且默认的MAP数是4,通过-m去调整
4.1创建临时的商品基本信息表
create table tmp_product_click_basic_info
as
select u.product_id, u.city_id, c.city_name, c.area
from
(select product_id, city_id from user_click where day='2016-05-05' ) u
join
(select city_id, city_name,area from city_info) c
on u.city_id = c.city_id;
4.2创建各区域下各产品访问次数临时表
create table tmp_area_product_click_count
as
select
product_id, area, count(1) click_count
from
tmp_product_click_basic_info
group by
product_id, area
4.3获取完整的商品信息的各区域的访问次数
create table tmp_area_product_click_count_full_info
as
select
a.product_id, b.product_name, a.area, a.click_count
from
tmp_area_product_click_count a join product_info b
on a.product_id = b.product_id
4.4获取区域点击top3的商品。使用窗口函数row_number() over()
select *
from (
select
product_id, product_name,area, click_count,
row_number() over(partition by area order by click_count desc) rank
from
tmp_area_product_click_count_full_info
) t where t.rank <=3;
4.5创建一个topN结果表
create table area_product_click_count_top3
as
select t.*,'2016-05-05' as day
from (
select
product_id, product_name,area, click_count,
row_number() over(partition by area order by click_count desc) rank
from
tmp_area_product_click_count_full_info
) t where t.rank <=3;
4.6使用sqoop将topn的结果导入到mysql数据库。
#在mysql中创建一个top3的点击表
create table area_product_click_count_top3
(product_id int(11),
product_name varchar(255),
area varchar(255),
click_count int(11),
rank int(11),
day varchar(20))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
#使用sqoop将hive中的数据导出到mysql
sqoop export \
--connect jdbc:mysql://localhost:3306/test \
--username root --password 123456 \
--table area_product_click_count_top3 \
--columns product_id,product_name,area,click_count,rank,day \
--export-dir /user/hive/warehouse/hive.db/area_product_click_count_top3 \
--input-fields-terminated-by '\001' \
-m 2
此时我们可以从msyql的area_product_click_count_top3中查询出TopN的结果。若我们再次执行导出的语句会发现相同的数据会存在两份。故优化添加两行配置重新导入数据。
sqoop export \
--connect jdbc:mysql://localhost:3306/test \
--username root --password 123456 \
--table area_product_click_count_top3 \
--columns product_id,product_name,area,click_count,rank,day \
--update-key product_id \
--update-mode updateonly \
--export-dir /user/hive/warehouse/hive.db/area_product_click_count_top3 \
--input-fields-terminated-by '\001' \
-m 2
扩展5:等值连接[“=”,join ,inner join],显示左右表共有的部分,即字段值在左右表都出现了。
扩展6:大数据最好采取列式存储数据,因为如果一行的字段很多上百以上,即使只查询几个字段,行存储数据,在sql查询时依旧会查询所有字段,高IO。
至此整个流程完成,上述整个流程是每天定时运行的,故我们可以编写一个shell脚本将hive的sql语句写进去,使用定时器定时的去执行。 这种处理是典型的离线处理方案。另外,上面很多group by 这可能会导致数据倾斜,那么数据倾斜应该怎么去解决???(面试必问)