工作中需要用到将hive的数据导一份到mysql中,需求是这样的:hive每天会产生一份用户标签(tag)发生变化的结果表user_tag,这份结果同步到mysql中,并且保持一份全量表,存储当前用户的标签。最初打算是在mysql建立一个分区表,按照天存储user_tag,研究了一下mysql的分区表,最终没有使用,既然学习了就做一下笔记。

mysql按照时间分区

mysql的分区方法分为好几种rangelisthashkey等方法,具体可以自行搜索一下,这里要讲的是range方法,下面是建表语句

CREATE TABLE `histdata` (
`uid` char(36) NOT NULL,
`date` date NOT NULL,
`cate` int(11) DEFAULT NULL
)
PARTITION BY RANGE COLUMNS(`date`)
(PARTITION histdata20180101 VALUES LESS THAN ('2018-01-02'),
PARTITION histdata20180102 VALUES LESS THAN ('2018-01-03'))

mysql分区表建表的时候需要指定好分区,与hive的分区有很大的不同,并且分区的名字也需要注意,因为这里面使用的是LESS THAN,那么如果每天都需要添加新的分区呢?那就需要修改表了

alter table histdata add PARTITION (PARTITION histdata20180103 VALUES LESS THAN ('2018-01-04'));

手动添加分区太麻烦了,那么能不能自动添加分区呢? 当然可以,使用存储过程。上学那会经常写java web,一些业务就直接写成了触发器、能够省下不少的代码,下面是存储过程代码:

DELIMITER $$
USE `test_db`$$ -- database name
DROP PROCEDURE IF EXISTS `histdata_add_partition`$$
CREATE DEFINER=`root`@`%` PROCEDURE `histdata_add_partition`()
BEGIN
SELECT REPLACE(partition_name,'histdata','') INTO @partition_name FROM INFORMATION_SCHEMA.PARTITIONS
WHERE table_name='histdata' ORDER BY partition_ordinal_position DESC LIMIT 1;
SET @head_date= DATE(DATE_ADD(@partition_name, INTERVAL 1 DAY))+0;
SET @rear_date= DATE(DATE_ADD(@partition_name, INTERVAL 2 DAY));
SET @s1=CONCAT('ALTER TABLE histdata ADD PARTITION (PARTITION histdata',@head_date,' VALUES LESS THAN (''',DATE(@rear_date),'''))');
SELECT @s1;
PREPARE stmt2 FROM @s1;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
COMMIT ;
END$$
DELIMITER ;

上面的作用是从当前分区中找到最大的一个,然后进行时间累加,再创建新的分区,再定义一个事件触发器

DELIMITER $$
CREATE EVENT histdata_event
ON SCHEDULE
EVERY 1 day STARTS '201x-0x-2x 23:59:59'
DO
BEGIN
CALL `test_db`.`histdata_add_partition`;
END $$
DELIMITER ;

show create table 看一下效果:

CREATE TABLE `histdata` (
`uid` char(36) NOT NULL,
`date` date NOT NULL,
`cate` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE COLUMNS(`date`)
(PARTITION histdata20180101 VALUES LESS THAN ('2018-01-02') ENGINE = InnoDB,
PARTITION histdata20180102 VALUES LESS THAN ('2018-01-03') ENGINE = InnoDB,
PARTITION histdata20180103 VALUES LESS THAN ('2018-01-04') ENGINE = InnoDB,
PARTITION histdata20180104 VALUES LESS THAN ('2018-01-05') ENGINE = InnoDB,
PARTITION histdata20180105 VALUES LESS THAN ('2018-01-06') ENGINE = InnoDB,
PARTITION histdata20180106 VALUES LESS THAN ('2018-01-07') ENGINE = InnoDB)

可以看到效果很不错,添加了分区。不过由于分区表需要修改表添加分区,涉及到权限问题,最终并没有使用。

使用sqoop同步

下面是所修要用到表的信息,需要先将hive中的数据同步到user_tag中,然后再讲user_tag的内容insert or update 到user_tag_all中,注意到user_tag_all这个表是有主键的

全量表:user_tag_all

用于存储最新的用户Tag,mid为用户id,tag为用户标签,dt为更新日期

CREATE TABLE `user_tag_all` (
`mid` int(15) NOT NULL,
`tag` tinyint(4) NOT NULL,
`dt` date NOT NULL,
PRIMARY KEY (`mid`)
) ;

每日同步表:user_tag

每日从hive中同步到mysql中,为用户的历史标签信息

CREATE TABLE `user_tag` (
`mid` int(15) NOT NULL,
`tag` tinyint(4) NOT NULL,
`dt` date NOT NULL
);

容错表:user_tag_staging

用于sqoop容错

CREATE TABLE `user_tag_staging` (
`mid` int(15) NOT NULL,
`tag` tinyint(4) NOT NULL,
`dt` date NOT NULL
);

使用的sqoop 导出命令,相关教程网上较多请自行查找

sqoop export -D mapreduce.job.queuename=sqoop
--connect jdbc:mysql://localhost:3306/dbname
--username root
--password root_pwd
--table user_tag
--staging-table user_tag_staging
--clear-staging-table
-m 1
--export-dir /user/hadoop/user_tag/dt=2018-03-27
--null-string '\\N'
--null-non-string '\\N'
--fields-terminated-by \001

值得注意的是staging-table这个是一个与目标表结构一样的表,是一个中间表,目的是用于对sqoop export进行容错,clear-staging-table将表清空。在操作的过程中自己遇到的的一个问题是mysql表比hive中的表多了dt字段,导致同步的时候一直报错,最终在hive中添加了一个字段用于存储时间(名字任意),实际上sqoop同步中它先从mysql中查询一条数据,解析出数据的类型,生成一个java文件,再对hdfs文件进行解析,并将数据逐条插入到mysql中,全程与hive无关。接下来就就是插入或者更新user_tag_all这个表了

insert into user_tag_all(mid,tag,dt) select mid,tag,dt from user_tag where dt='2018-03-16' ON DUPLICATE KEY UPDATE tag=VALUES(tag),dt=VALUES(dt);

总结####

本篇文章虽然任务不大,但是从中有许多值得借鉴的知识点

  • mysql分区表的使用,以及存储过程的编写
  • mysql的不存在则插入、存在则更新的使用
  • sqoop命令的使用,中间表的作用

ref###

MySQL每天自动增加分区

记一次sqoop同步到mysql的更多相关文章

  1. 记录sqoop同步失败问题解决过程,过程真的是很崎岖。(1月6日解决)

    记录sqoop同步失败问题解决过程,过程真的是很崎岖.事发原因:最近突然出现sqoop export to mysql时频繁出错.看了下日志是卡在某条数据过不去了,看异常.看sqoop生成的mr并未发 ...

  2. Sqoop使用,mysql,hbase,hive等相互转换

    Sqoop 是一款用来在不同数据存储软件之间进行数据传输的开源软件,它支持多种类型的数据储存软件. 安装 Sqoop 1.下载sqoop并加mysql驱动包 http://mirror.bit.edu ...

  3. sqoop导出到mysql中文乱码问题总结、utf8、gbk

    sqoop导出到mysql中文乱码问题总结.utf8.gbk 今天使用sqoop1.4.5版本的(hadoop使用cdh5.4)因为乱码问题很是头痛半天.下面进行一一总结 命令: [root@sdzn ...

  4. sqoop用法之mysql与hive数据导入导出

    目录 一. Sqoop介绍 二. Mysql 数据导入到 Hive 三. Hive数据导入到Mysql 四. mysql数据增量导入hive 1. 基于递增列Append导入 1). 创建hive表 ...

  5. 异构平台同步(Mysql到Oracle)

    Oracle GoldenGate学习之--异构平台同步(MySQL到Oracle) 如图所示:源端采用Mysql库,目标端采用Oracle库 一.OGG安装配置(源端) 1.OGG下载 https: ...

  6. MySQL数据库的同步配置+MySql读写分离

    使用mysql主从复制的好处有: 1.采用主从服务器这种架构,稳定性得以提升.如果主服务器发生故障,我们可以使用从服务器来提供服务. 2.在主从服务器上分开处理用户的请求,可以提升数据处理效率. 3. ...

  7. sqoop命令,mysql导入到hdfs、hbase、hive

    1.测试MySQL连接 bin/sqoop list-databases --connect jdbc:mysql://192.168.1.187:3306/trade_dev --username ...

  8. 043 hive数据同步到mysql

    一:意义 1.意义 如果可以实现这个功能,就可以使用spark代替sqoop,功能程序就实现这个功能. 二:hive操作 1.准备数据 启动hive 否则报错,因为在hive与spark集成的时候,配 ...

  9. 从hbase到hive,以及sqoop转到mysql解析

    https://blog.csdn.net/qq_33689414/article/details/80328665 hive关联hbase的配置文件 hive和hbase同步https://cwik ...

随机推荐

  1. java中equals和==以及toString

    我们通常在控制台输出时使用System.out.print(),print只能直接输出基本类型和字符串,对于其他的类型直接输出将会输出@开头的引用,因此若需要输出对应的内容则需要使用toSring方法 ...

  2. Caused by: java.lang.ClassNotFoundException: org.jbpm.pvm.internal.processengine.SpringHelper

    1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...

  3. 谈下spring下的 aop日志记录

    在我们开发当中  我们需要对系统用户行为和 系统异常信息有个统一记录  以便后期的 用户行为分析和bug修复   当我们有这个需求时  我们的通常采取方式很多 1.比如我们定义一个规范 开发一个接口 ...

  4. zookeeper选举

    什么时候开始进行选举 1.服务器初始化启动的时候2.服务器运行期间连接不上leader的时候 初始化选举过程 进行leader选举至少需要两台服务器,我们这里举例为5台服务器(1,2,3,4,5)1. ...

  5. C#图解教程 第十一章 枚举

    枚举 枚举 设置底层类型和显式值隐式成员编号 位标志 Flags特性使用位标志的示例 关于枚举的补充 枚举 枚举 枚举是由程序员定义的类型与类或结构一样. 与结构一样,枚举是值类型,因此直接存储它们的 ...

  6. 由内搜推送思考Kafka 的原理

    刚入公司的两周多,对CDX项目有了进一步的认识和理解,在这基础上,也开始了解部门内部甚至公司提供的一些中间服务.CDX项目中涉及到的二方服务和三方服务很多,从之前写过的SSO,Auth,到三方图库的各 ...

  7. I2C总线协议的软件模拟实现方法

    I2C总线协议的软件模拟实现方法 在上一篇博客中已经讲过I2C总线通信协议,本文讲述I2C总线协议的软件模拟实现方法. 1. 简述 所谓的I2C总线协议的软件模拟实现方法,就是用软件控制GPIO的输入 ...

  8. Angular通过订阅观察者对象实现不同组件中数据的实时传递

    在angular官方定义中,组件直接的数据交换只要在父子直接传递,但是我们在项目中经常需要在各种层级之间传递数据,下面介绍关于订阅可观察对象实现的数据传递. 首先定义一个服务app.sevice.ts ...

  9. gradle build docker image

    前言:其实gradle-docker插件干的事和我们手动制作镜像是一样的,只不过它封装了一些步骤而已. eg:如果我们要将项目打包成镜像,首先我们要写Dockerfile,这是制作镜像的不可或缺的第一 ...

  10. WordPress非插件实现评论回复邮件提醒通知

    要想在第一时间知道有人在自己博客留言,然后在第一时间回复留言再第一时间通知邮件者,这就需要WordPress博客拥有邮件通知功能. 先看效果: 评论邮件通知的方法: 1.所有回复都发送邮件通知 登陆博 ...