Hive和MySQL数据互相导入

在实际场景中,举例子说明:

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

执行user_visited_data.sh脚本,就可以实现插入了


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

事实上,Sqoob也能实现从Hive到MySQL的数据导入,方法和第二种也是类似的

还有很多导入,比如从HDFS导入MySQL、Hive,从本地HDFS导入,思想都是类似的


你可能感兴趣的:(Hive)