分库分表mysql同步数据到hive中
一、背景及问题
背景概括
- 分表100张
- 数据量8.6亿
- 需要使用datax从mysql同步至hdfs(hive)
- 之前是100个datax任务写入ods层的一张合并表,构建二级分区,一级是加载日期,二级是分表的编号
- 之前是每日全量
${}为传参
- char(9) \t 水平制表符
- char(10) \r 回车
- char(13) \n 换行
修改前datax代码简化参考
{
"job": {
"setting": {
"speed": {
"channel": 5
},
"errorLimit":{
"record":0,
"percentage":0
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "${SRC_MYSQL_业务名称_USR}",
"password": "${SRC_MYSQL_业务名称_PWD}",
"connection": [
{
"querySql": [
"select
id,
pro_id,
rtrim(ltrim(replace(replace(replace(device_id,char(9),''),char(10),''),char(13),''))),
'${CURRENT_FLOW_START_DAY}',
${EXECUTION_ID}
from ${SRC_MYSQL_业务名称_DB_库名称}.表名称_98"
],
"jdbcUrl": [
"${SRC_MYSQL_业务名称_URL}"
]
}
]
}
},
"writer": {
"name": "hdfswriter",
"parameter": {
"column": [
{
"name": "id",
"type": "bigint"
},
{
"name": "pro_id",
"type": "bigint"
},
{
"name": "device_id",
"type": "string"
},
{
"name": "op_time",
"type": "string"
},
{
"name": "execution_id",
"type": "string"
}
],
"defaultFS": "${HDFS_ROOT_URI}",
"fieldDelimiter": "\t",
"fileName": "表名称",
"fileType": "orc",
"path": "${HDFS_HV_EXTTB_ROOT}/${HIVE_DB_ODS_业务名称}/表名称/load_date=${CURRENT_FLOW_START_DAY}/record_id=98",
"writeMode": "append"
},
"extendScript": {
"post": [
{
"type":"hql",
"script":"ALTER TABLE ${HIVE_DB_ODS_业务名称}.表名称 ADD IF NOT EXISTS PARTITION(load_date='${CURRENT_FLOW_START_DAY}',record_id='98')"
}
]
}
}
}
]
}
}
二、解决
快速上手
本质:将"querysql"拆分成"column","where","table",MysqlReader根据指定的column、table、where条件拼接SQL
- 改动一
- "channel"由5改为20
并发task数。看自己需求调整
- "channel"由5改为20
- 改动二
- 将"querySql"中的列挑选出来,放入"column"中,与"connection"同一层级
记得加双引号
- 将"querySql"中的列挑选出来,放入"column"中,与"connection"同一层级
- 改动三
- 新增"where",与"connection"同一层级,
将全量改为增量抽取
- 新增"where",与"connection"同一层级,
- 改动四
- 将"querySql"中的表挑选出来,放入"table"中,在"connection"下,与"jdbcUrl"同一层级
将100张表放入一个脚本
- 将"querySql"中的表挑选出来,放入"table"中,在"connection"下,与"jdbcUrl"同一层级
- 改动五
- 改写hdfswriter的 “path"和"script”,去掉二级分区(原分表编号)
修改后datax代码简化参考
{
"job": {
"setting": {
"speed": {
"channel": 20
},
"errorLimit":{
"record":0,
"percentage":0
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "${SRC_MYSQL_业务名称_USR}",
"password": "${SRC_MYSQL_业务名称_PWD}",
"column": [
"id",
"pro_id",
"rtrim(ltrim(replace(replace(replace(device_id,char(9),''),char(10),''),char(13),'')))",
"update_time",
"${CURRENT_FLOW_START_DAY}",
"${EXECUTION_ID}"
],
"where": "date_format(update_time,'%Y-%m-%d') >='${START_DATEKEY}'",
"connection": [
{
"table": [
"${SRC_MYSQL_业务名称_DB_库名称}.表名称_0",
。。。。。。。此处省略。。。。。。。。。
"${SRC_MYSQL_业务名称_DB_库名称}.表名称_99"
],
"jdbcUrl": [
"${SRC_MYSQL_业务名称_URL}"
]
}
]
}
},
"writer": {
"name": "hdfswriter",
"parameter": {
"column": [
{
"name": "id",
"type": "bigint"
},
{
"name": "pro_id",
"type": "bigint"
},
{
"name": "device_id",
"type": "string"
},
{
"name": "update_time",
"type": "string"
},
{
"name": "op_time",
"type": "string"
},
{
"name": "execution_id",
"type": "string"
}
],
"defaultFS": "${HDFS_ROOT_URI}",
"fieldDelimiter": "\t",
"fileName": "表名称",
"fileType": "orc",
"path": "${HDFS_HV_EXTTB_ROOT}/${HIVE_DB_ODS_业务名称}/表名称/load_date=${CURRENT_FLOW_START_DAY}",
"writeMode": "append"
},
"extendScript": {
"post": [
{
"type":"hql",
"script":"ALTER TABLE ${HIVE_DB_ODS_业务名称}.表名称 ADD IF NOT EXISTS PARTITION(load_date='${CURRENT_FLOW_START_DAY}')"
}
]
}
}
}
]
}
}
修改后ods层到dwd层简化参考sql
原先的全量变增量
use ${HIVE_DB_DWD_业务名称};
insert overwrite table dwd_表名称
select
t.id,
t.pro_id,
t.device_id,
t.update_time,
t.op_time,
t.execution_id,
'${CURRENT_FLOW_START_DAY}' as load_date
from (
select --取当天增量数据/重跑的全部数据
ods.id,
ods.pro_id,
ods.device_id,
ods.update_time,
ods.op_time,
ods.execution_id
from (select *
from ${HIVE_DB_ODS_业务名称}.表名称
where load_date = '${CURRENT_FLOW_START_DAY}'
) ods
union all
select --如果是增量数据,取原数据,否则,不取
dwd.id,
dwd.pro_id,
dwd.device_id,
dwd.update_time,
dwd.op_time,
dwd.execution_id
from (select *
from ${HIVE_DB_DWD_业务名称}.表名称
) dwd
left join (select *
from ${HIVE_DB_ODS_业务名称}.表名称
where load_date = '${CURRENT_FLOW_START_DAY}'
)ods
on dwd.id=ods.id
where ods.id is null
)t
;
修改点参数说明
table
- 描述:所选取的需要同步的表。使用JSON的数组描述,因此支持多张表同时抽取。当配置为多张表时,用户自己需保证多张表是同一schema结构,MysqlReader不予检查表是否同一逻辑表。注意,table必须包含在connection配置单元中。
- 必选:是
- 默认值:无
column
- 描述:所配置的表中需要同步的列名集合,使用JSON的数组描述字段信息。用户使用代表默认使用所有列配置,例如[’’]。
支持列裁剪,即列可以挑选部分列进行导出。
支持列换序,即列可以不按照表schema信息进行导出。
支持常量配置,用户需要按照Mysql SQL语法格式: [“id”, “table
”, “1”, “‘bazhen.csy’”, “null”, “to_char(a + 1)”, “2.3” , “true”] id为普通列名,table
为包含保留在的列名,1为整形数字常量,'bazhen.csy’为字符串常量,null为空指针,to_char(a + 1)为表达式,2.3为浮点数,true为布尔值。 - 必选:是
- 默认值:无
splitPk
- 描述:MysqlReader进行数据抽取时,如果指定splitPk,表示用户希望使用splitPk代表的字段进行数据分片,DataX因此会启动并发任务进行数据同步,这样可以大大提供数据同步的效能。
推荐splitPk用户使用表主键,因为表主键通常情况下比较均匀,因此切分出来的分片也不容易出现数据热点。
目前splitPk仅支持整形数据切分,不支持浮点、字符串、日期等其他类型。如果用户指定其他非支持类型,MysqlReader将报错!
如果splitPk不填写,包括不提供splitPk或者splitPk值为空,DataX视作使用单通道同步该表数据。 - 必选:否
- 默认值:空
where
- 描述:筛选条件,MysqlReader根据指定的column、table、where条件拼接SQL,并根据这个SQL进行数据抽取。在实际业务场景中,往往会选择当天的数据进行同步,可以将where条件指定为gmt_create > $bizdate。注意:不可以将where条件指定为limit 10,limit不是SQL的合法where子句。
where条件可以有效地进行业务增量同步。如果不填写where语句,包括不提供where的key或者value,DataX均视作同步全量数据。 - 必选:否
- 默认值:无
querySql
- 描述:在有些业务场景下,where这一配置项不足以描述所筛选的条件,用户可以通过该配置型来自定义筛选SQL。当用户配置了这一项之后,DataX系统就会忽略table,column这些配置型,直接使用这个配置项的内容对数据进行筛选,例如需要进行多表join后同步数据,使用select a,b from table_a join table_b on table_a.id = table_b.id
当用户配置querySql时,MysqlReader直接忽略table、column、where条件的配置,querySql优先级大于table、column、where选项。 - 必选:否
- 默认值:无
参考地址:
https://github.com/alibaba/DataX/blob/master/mysqlreader/doc/mysqlreader.md