DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、DRDS 等各种异构数据源之间高效的数据同步功能。
关于原理及优缺点,知乎上有博主描述:DataX介绍以及优缺点分析 - 知乎
笔者比较赞同
阿里相关文档地址:https://github.com/alibaba/DataX
官方部分参数说明(这里以Oracle读,Oracle写为例,关系型数据库参数基本一样)
{
"job": {
"setting": {
"speed": {
// 设置传输速度 byte/s 尽量逼近这个速度但是不高于它.
// channel 表示通道数量,byte表示通道速度,如果单通道速度1MB,
配置byte为1048576表示一个channel
"byte": 1048576
},
//出错限制
"errorLimit": {
//先选择record,出错多少条抛异常,为零代表报错就抛异常,任务失败
"record": 0,
//百分比 1表示100%
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "oraclereader",
"parameter": {
// 数据库连接用户名
"username": "root",
// 数据库连接密码
"password": "root",
"column": [
"id","name"
],
//切分主键
"splitPk": "db_id",
"connection": [
{
"table": [
"table"
],
"jdbcUrl": [
"jdbc:oracle:thin:@[HOST_NAME]:PORT:[DATABASE_NAME]"
]
}
]
}
},
"writer": {
"name": "oraclewriter",
"parameter": {
"username": "root",
"password": "root",
"column": [
"id",
"name"
],
"preSql": [
"delete from test"
],
"connection": [
{
"jdbcUrl": "jdbc:oracle:thin:@[HOST_NAME]:PORT:[DATABASE_NAME]",
"table": [
"test"
]
}
]
}
}
}
]
}
}
关系型数据库参数解释说明(红色为必填参数,橙色表示要填但可以被其他参数替换,黑色表示可以不填):
setting:
speed:数据传输速度
channel:通道数量
byte:传输速度 byte/s 尽量逼近这个速度但是不高于它
errorLimit:数据容错数
record:出错多少条抛异常,为零代表报错就抛异常,任务失败
percentage:出错率,1表示100%,条数和概率都配置了则优先条数然后再判断百分比
content:
reader:
name:根据读取的数据源固定名称:*reader,例如【mysqlreader,oraclereader,sqlserverreader...】
fetchSize:mysql不支持这个参数,该配置项定义了插件和数据库服务器端每次批量数据获取条数,该值决定了DataX和服务器端的网络交互次数,能够较大的提升数据抽取性能。不宜设置过大超过2048可能会造成Datax进程OOM,默认1024
parameter:
username:数据库用户名
password: 数据库密码
splitPk:进行数据抽取时,如果指定splitPk,表示用户希望使用splitPk代表的字段进行数据分片,DataX因此会启动并发任务进行数据同步,这样可以大大提供数据同步的效能。推荐splitPk用户使用表主键,因为表主键通常情况下比较均匀,因此切分出来的分片也不容易出现数据热点。目前splitPk仅支持整形、字符串型数据切分
column:指定列(注意,如果设置了querySql,此字段可以不写)
where:查询条件(注意,如果设置了querySql,此字段可以不写)
connection:
table:指定表名(注意,如果设置了querySql,此字段可以不写)
querySql:指定查询的sql语句(描述:在有些业务场景下,where这一配置项不足以描述所筛选的条件,用户可以通过该配置型来自定义筛选SQL。当用户配置了这一项之后,DataX系统就会忽略table,column这些配置型,直接使用这个配置项的内容对数据进行筛选,例如需要进行多表join后同步数据,使用select a,b from table_a join table_b on table_a.id = table_b.id;个人推荐使用,如果不设置,请填写column和table两个字段,where可以不写,会默认全表数据,如果设置了column,table,where三个字段会失效)
jdbcUrl:指定数据库连接
writer:
name:根据写入的数据源固定名称:*writer,例如【mysqlwriter,oraclewriter,sqlserverwriter...】
parameter:
username:数据库用户名
password: 数据库密码
writeMode:oracle,postgresql,sqlserver不支持这个参数,控制写入数据到目标表采用 insert into 或者 replace into 或者 ON DUPLICATE KEY UPDATE 语句,所有选择(insert/replace/update)
column:指定列
preSql:写入数据到目的表前,会先执行这里的标准语句。
postSql:写入数据到目的表后,会执行这里的标准语句。
batchSize:一次性批量提交的记录数大小,该值可以极大减少DataX与Mysql的网络交互次数,并提升整体吞吐量。但是该值设置过大可能会造成DataX运行进程OOM情况。默认1024
session:描述:控制写入数据的时间格式,时区等的配置,如果表中有时间字段,配置该值以明确告知写入 oracle 的时间格式。通常配置的参数为:NLS_DATE_FORMAT,NLS_TIME_FORMAT。其配置的值为 json 格式
例如
"session": [
"alter session set NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss'",
"alter session set NLS_TIMESTAMP_FORMAT='yyyy-mm-dd hh24:mi:ss'",
"alter session set NLS_TIMESTAMP_TZ_FORMAT='yyyy-mm-dd hh24:mi:ss'",
"alter session set TIME_ZONE='US/Pacific'",
"set session sql_mode='ANSI'"
]
connection:
table:指定表名
jdbcUrl:指定数据库连接
注意事项:
执行 DataX 的机器参数为:
-
cpu: 24 Core Intel(R) Xeon(R) CPU E5-2430 0 @ 2.20GHz
-
mem: 94GB
-
net: 千兆双网卡
-
disc: DataX 数据不落磁盘,不统计此项
Oracle 数据库机器参数为:
-
cpu: 4 Core Intel(R) Xeon(R) CPU E5420 @ 2.50GHz
-
mem: 7GB
DataX jvm 参数
-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError
通道数 | 批量提交行数 | DataX速度(Rec/s) | DataX流量(MB/s) | DataX机器网卡流出流量(MB/s) | DataX机器运行负载 | DB网卡进入流量(MB/s) | DB运行负载 |
1 | 128 | 15564 | 6.51 | 7.5 | 0.02 | 7.4 | 1.08 |
1 | 512 | 29491 | 10.90 | 12.6 | 0.05 | 12.4 | 1.55 |
1 | 1024 | 31529 | 11.87 | 13.5 | 0.22 | 13.3 | 1.58 |
1 | 2048 | 33469 | 12.57 | 14.3 | 0.17 | 14.3 | 1.53 |
1 | 4096 | 31363 | 12.48 | 13.4 | 0.10 | 10.0 | 1.72 |
4 | 10 | 9440 | 4.05 | 5.6 | 0.01 | 5.0 | 3.75 |
4 | 128 | 42832 | 16.48 | 18.3 | 0.07 | 18.5 | 2.89 |
4 | 512 | 46643 | 20.02 | 22.7 | 0.35 | 21.1 | 3.31 |
4 | 1024 | 39116 | 16.79 | 18.7 | 0.10 | 18.1 | 3.05 |
4 | 2048 | 39526 | 16.96 | 18.5 | 0.32 | 17.1 | 2.86 |
4 | 4096 | 37683 | 16.17 | 17.2 | 0.23 | 15.5 | 2.26 |
8 | 128 | 38336 | 16.45 | 17.5 | 0.13 | 16.2 | 3.87 |
8 | 512 | 31078 | 13.34 | 14.9 | 0.11 | 13.4 | 2.09 |
8 | 1024 | 37888 | 16.26 | 18.5 | 0.20 | 18.5 | 3.14 |
8 | 2048 | 38502 | 16.52 | 18.5 | 0.18 | 18.5 | 2.96 |
8 | 4096 | 38092 | 16.35 | 18.3 | 0.10 | 17.8 | 3.19 |
16 | 128 | 35366 | 15.18 | 16.9 | 0.13 | 15.6 | 3.49 |
16 | 512 | 35584 | 15.27 | 16.8 | 0.23 | 17.4 | 3.05 |
16 | 1024 | 38297 | 16.44 | 17.5 | 0.20 | 17.0 | 3.42 |
16 | 2048 | 28467 | 12.22 | 13.8 | 0.10 | 12.4 | 3.38 |
16 | 4096 | 27852 | 11.95 | 12.3 | 0.11 | 12.3 | 3.86 |
32 | 1024 | 34406 | 14.77 | 15.4 | 0.09 | 15.4 | 3.55 |
-
批量提交行数(batchSize)对性能影响很大,当 batchSize>=512 之后,单线程写入速度能达到每秒写入一万行
-
在 batchSize>=512 的基础上,随着通道数的增加(通道数<32),速度呈线性比增加。
-
通常不建议写入数据库时,通道个数 >32
-
参数解释参照github上的官方文档,基本较全,读者也可自行登录官方地址查阅
例子:
-
读mysql数据写入到oracle
读数据源mysql表名:datax_test 字段:id,name, create_time
写数据源oracle表名:DATAX_TEST1 字段:ID1,NAME1,CREATE_TIME1
{
"job": {
"setting": {
"speed": {
"channel": 1,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "root",
"splitPk": "id",
"connection": [
{
"querySql": [
"SELECT id ID1,name NAME1,create_time CREATE_TIME1 FROM datax_test"
],
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/mysql?useCursorFetch=true"
]
}
]
}
},
"writer": {
"name": "oraclewriter",
"parameter": {
"username": "root",
"password": "root",
"column": [
"\"ID1\"",
"\"NAME1\"",
"\"CREATE_TIME1\""
],
"connection": [
{
"table": [
"DATAX_TEST1"
],
"jdbcUrl": "jdbc:oracle:thin:@127.0.0.1:1521:orcl"
}
]
}
}
}
]
}
}
2.读oracle数据写入到oracle
读数据源oracle表名:DATAX_TEST 字段:ID,NAME, CREATE_TIME
写数据源oracle表名:DATAX_TEST1 字段:ID1,NAME1,CREATE_TIME1
{
"job": {
"setting": {
"speed": {
"channel": 1,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "oraclereader",
"parameter": {
"username": "root",
"password": "root",
"splitPk": "ID",
"connection": [
{
"querySql": [
"SELECT ID ID1,NAME NAME1,CREATE_TIME CREATE_TIME1 FROM DATAX_TEST"
],
"jdbcUrl": [
"jdbc:oracle:thin:@127.0.0.1:1521:orcl"
]
}
]
}
},
"writer": {
"name": "oraclewriter",
"parameter": {
"username": "root",
"password": "root",
"column": [
"\"ID1\"",
"\"NAME1\"",
"\"CREATE_TIME1\""
],
"connection": [
{
"table": [
"DATAX_TEST1"
],
"jdbcUrl": "jdbc:oracle:thin:@127.0.0.1:1521:orcl"
}
]
}
}
}
]
}
}
3.读sqlserver数据写入到oracle
读数据源sqlserver表名:[guest].[datax_test] 字段:id,name, create_time
写数据源oracle表名:DATAX_TEST1 字段:ID1,NAME1,CREATE_TIME1
{
"job": {
"setting": {
"speed": {
"channel": 1,
"byte": 1048576
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "sqlserverreader",
"parameter": {
"username": "root",
"password": "root",
"splitPk": "id",
"connection": [
{
"querySql": [
"SELECT id ID1,name NAME1,create_time CREATE_TIME1 FROM [guest].[datax_test]"
],
"jdbcUrl": [
"jdbc:sqlserver://127.0.0.1:1433;DatabaseName=DRGSTEST"
]
}
]
}
},
"writer": {
"name": "oraclewriter",
"parameter": {
"username": "root",
"password": "root",
"column": [
"\"ID1\"",
"\"NAME1\"",
"\"CREATE_TIME1\""
],
"connection": [
{
"table": [
"DATAX_TEST1"
],
"jdbcUrl": "jdbc:oracle:thin:@127.0.0.1:1521:orcl"
}
]
}
}
}
]
}
}