在实际场景中,举例子说明:
1· 数据从Hive导入MySQL:
先在MySQL中建表:
CREATE TABLE `dg_user_visited` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL COMMENT '用户id',
`agent_id` char(100) NOT NULL,
`visitedtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最近访问时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户最后登录时间表';
由2个脚本实现:
user_visited_data.sh:
#!/bin/sh
. /etc/profile
if [ $# -eq 0 ]
then
time_id=`date -d "-1 day" +%Y%m%d`
BEGIN_DATE=`date -d "-1 day" +%Y-%m-%d`
END_DATE=`date -d "-1 day" +%Y-%m-%d`
CUR_DATE=`date -d "-1 day" +%Y-%m-%d`
CUR_PARTITION=`date -d "-1 day" +%Y%m%d`
YESTERDAY_PARTITION=`date -d "-2 day" +%Y%m%d`
elif [ $# -eq 1 ]
then
format_day=`echo $1|grep -o '[0-9]\{8\}'`
format_hour=`echo $1|grep -o '[0-9]\{2\}$'`
BEGIN_DATE=`date -d "$format_day" +%Y-%m-%d`
END_DATE=`date -d "$format_day" +%Y-%m-%d`
CUR_DATE=`date -d "$format_day" +%Y-%m-%d`
CUR_PARTITION=`date -d "$format_day" +%Y%m%d`
YESTERDAY_PARTITION=`date -d "-1 day $format_day" +%Y%m%d`
else
echo "the args is wrong ,you should give it like '2014092307'"
exit 1;
fi
# 判断参数,为时间取值
echo $BEGIN_DATE
echo $END_DATE
echo "CUR_PARTIOTION: ${CUR_PARTITION}"
# work dir
WORK_DIR="/opt/DATA/goldmine/src/service/app_login_agent"
query="select req[\"uid\"] as user_id,req[\"agentid\"] as agent_id,MAX(time) as visitedtime \
from dh_server_log \
where p_day = ${CUR_PARTITION} and req[\"uid\"]>0 \
group by req[\"uid\"],req[\"agentid\"]"
hive -e "${query}" >${WORK_DIR}/data/tmpDataUserVistedData_${CUR_PARTITION}.log
cat ${WORK_DIR}/data/tmpDataUserVistedData_${CUR_PARTITION}.log | awk -F '\t' '{print $1"^"$2"^"$3}' | sed 's/NULL/0/g' >${WORK_DIR}/data/dataUserVistedData_${CUR_PARTITION}.log
# 写出查询数据的SQL,把查询到的数据先保存在文本文件中
# awk -F '\t' '{print $1"^"$2"^"$3}' :使用awk命令,把查询到的数据字段,每行用 ^ 来隔开
# Hive查询到的结果默认每行的字段间以 \t分割
# sed 's/NULL/0/g' sed命令把NULL值替换为0,以免在后面的insert操作中出现 badSql报错
rm ${WORK_DIR}/data/tmpDataUserVistedData_${CUR_PARTITION}.log
#rm ${WORK_DIR}/data/dataUserVistedData_${YESTERDAY_PARTITION}.log
# insert data
sh ${WORK_DIR}/insert_user_visited_data.sh ${CUR_DATE} ${WORK_DIR}/data/dataUserVistedData_${CUR_PARTITION}.log
# 调用另一个脚本执行插入操作
insert_user_visited_data.sh :
if [ $# -ne 2 ]; then
echo $0 "day STAT_TYPE USER_TYPE TIME_TYPE TIME_TYPE_VALUE FILE_DATE"
echo
exit 2
fi
# def vars
CUR_DATE=$1
FILE_DATA=$2
# 正如上一个脚本调用的那样,有2个参数,第一个时间,第二个为保存数据的log
#del data
sh /opt/DATA/goldmine/src/kpi/common_script/handleMysqlDBForDGDATA.sh "delete from dg_user_visited where date(visitedtime)= '${CUR_DATE}' "
# 先调用脚本,删除本来已经存在的可能错误的当天的数据
# insert data
while read line; # 读取数据文件的每一行(shell语法)
do
#echo $line
query=`echo $line | sed 's/^B/,/g' | awk -F '^' '{printf("%s,\"%s\",\"%s\"",$1,$2,$3)}' `
#这行命令实现了把上面提到的 ^ 分隔符替换为逗号
#值得注意的是awk命令中,printf中,写了%s,\"%s\",\"%s\",因为第二第三个字段为String类型,所以需要加上""并转义
#echo "query: $query"
#
statement=`echo "INSERT INTO dg_user_visited(user_id,agent_id,visitedtime) VALUES($query);"`
#echo "statement: $statement"
/opt/DATA/goldmine/src/kpi/common_script/handleMysqlDBForDGDATA.sh "$statement"
#调用脚本链接mysql实现插入
done < $FILE_DATA
#echo ${FILE_DATA}
#
if [[ $? -eq 0 ]]; then
#echo ${FILE_DATA}
echo "Wrote data into DB"
fi
handleMysqlDBForDGDATA.sh:
#!/bin/bash
# check args
if [ $# -ne 1 ]; then
echo $0 [script_sql]
echo
exit 2
fi
# def vars
USER="*****"
PWD="*****"
DATABASE="dgdata"
#
SCRIPT_SQL="${1}"
#
HOST="192.168.11.111"
#echo "${SCRIPT_SQL}"
# exec sql
/usr/local/mysql/bin/mysql -u $USER -p"${PWD}" --default-character-set=utf8 -h${HOST} $DATABASE -e "${SCRIPT_SQL}"
#链接MySQL
2· 从Mysql中导入数据到Hive中
这个就相对比较简单了,使用Sqoob
给出我写的脚本中的一部分以供参考:
#!/bin/sh
. /etc/profile
if [ $1 = 0 ];then
#
hadoop fs -ls /$2
elif [ $1 = dg_cook ];then
#import to hive - dg_cook
# del dir
hadoop fs -rm -r -f /user/dg-hadoop/dg_cook
#先删除表,以免数据混乱
sqoop import --connect "jdbc:mysql://1.1.1.1:3306" --username aaa--password "aaa" \
#链接mysql
--table dg_cook \
#指定表名
--hive-drop-import-delims \
--fields-terminated-by '\001' \
#指定字段分隔符 \001
--lines-terminated-by '\n' \
#指定行之间的分隔符 \n
--hive-import \
#import代表引入操作
--hive-overwrite \
#overwrite代表覆盖写入
--hive-table dg_cook
#设定Hive表名
#--validate
elif [ $1 = dg_recipe_rating ];then
#import to hive - dg_recipe_rating
# del dir
hadoop fs -rm -r -f /user/dg-hadoop/dg_recipe_rating
sqoop import --connect "jdbc:mysql://1.1.1.1:3306" --username aaa--password "aaa" \
--table dg_recipe_rating \
--hive-drop-import-delims \
--fields-terminated-by '\001' \
--lines-terminated-by '\n' \
--hive-import \
--hive-overwrite \
--hive-table dg_recipe_rating
#--validate
elif [ $1 = dg_watermark ];then
#import to hive - dg_watermark
# del dir
hadoop fs -rm -r -f /user/dg-hadoop/dg_watermark
sqoop import --connect "jdbc:mysql://1.1.1.1:3306" --username aaa--password "aaa" \
--table dg_watermark \
--hive-drop-import-delims \
--fields-terminated-by '\001' \
--lines-terminated-by '\n' \
--hive-import \
--hive-overwrite \
--hive-table dg_watermark
#--validate
还有很多导入,比如从HDFS导入MySQL、Hive,从本地HDFS导入,思想都是类似的