# 如何对 OceanBase 迁移性能进行简单分析和调优

## DataX 的调优建议

DataX 本质上是个数据交换平台，将源端的数据读出，写入到目标端。其数据迁移性能取决于下面几个因素：

+ 源端的读性能。可以加并发，制约条件就是对源库的影响、源库的性能瓶颈等。
+ DataX 自身的性能。DataX 是个Java程序，其能起的线程数也是有限，受限于所在主机的CPU和内存大小。
+ 网络传输性能。并发高的时候，网络传输要留意吞吐量是否达到网卡瓶颈。现在万兆网卡的吞吐量 10000Mb，很难达到。不过占用网络带宽对其他业务可能也会有影响。
+ 目标端的写入性能。也可以加并发，制约条件就是目标库写入性能瓶颈、对目标库的影响等。如果目标端是OB，需要针对OB调优。
+ 涉及到文件数据源的时候，关注文件所在磁盘 IO 性能。如 iops、吞吐量等。

所以 DataX 的调优就是调节 `reader` 和 `writer` 的各个并行参数，尽可能的把 源和目标端数据库资源能力都利用上，那么整体 DataX 的迁移效率会最好。

此外，如果主机内存够大的话， `datax.py` 能使用的 JVM 内存也可以调大。编辑脚本，调大 `-Xms` 和 `-Xmx` 参数。

```bash
vim bin/datax.py

 30 DEFAULT_JVM = "-Xms16g -Xmx16g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=%s/log" % (DATAX_HOME)
```

## 读写并行度

DataX 的配置文件中首先有 `speed` 的设置，其中 `channel` 是总的并发数。
OB 的 `oceanbasev10writer` 还进一步支持 多线程，通过参数 `"writerThreadCount":10` 指定每个 channel 从源端读取的数据，再分几个并发线程写入。所以OB总的写入并发数是  `channel` * `writerThreadCount` 。

每个 `writer` 里还有个 batchsize，那个是一个事务的记录数数量。通常建议 200-10000 都可以。尽量不要超过 1万。事务太大了，不是很好。在 OceanBase 里事务太大太长，可能会到达事务超时时间（默认120秒）。
这里有趣的是，OB 的 `oceanbasev10writer` 会把这个batch insert 合并为 一个 insert 多个values 子句。所以 `batchSize` 也不要太大；否则，insert sql 文本太长, 高并发时也可能会报错（内存不足方面的错误）。当列非常多的时候（比如说100 列） 或者 值的内容有大文本的时候，这个 `batchSize` 控制在 几百左右比较好。

## 源端数据库读优化

当源端是数据库的时候，如果表有单列主键，并且主键列类型的 数值型 （如 number、bigint、integer、decimal 等），可以在源端 `reader` 里增加配置 ： `"splitPk": "id"` 。这个时候，DataX 能先对主键进行切片，然后多个 channel 同时并发分段去读取源数据。 如果没有这个设置，那源端只能单并发读取数据。

## OB写入的内存调优

OB 的数据读写模型比较特殊，增量都在内存里。当 OceanBase 机器已经是 SSD 盘的时候， IO 不大可能会首先成为 OceanBase 的性能瓶颈，内存和 CPU 更有可能先是瓶颈。大量数据写入的时候，增量对 memtable 内存的消耗会很快。OB 设置不当的情况下，可能会出现内存耗尽，从而写入报错。其他业务写入也会跟着报错。

OB 的内存优化过程比较复杂。这里先给出一个初始的设置，能降低内存写入报错的概率。

```sql
alter system set merge_thread_count = 32;  --  增大合并的线程数。
alter system set minor_merge_concurrency = 16;  --  增大转储的线程数，期望提高转储的速度。
alter system set _mini_merge_concurrency = 8;  --  增大mini_merge的线程数，期望提高mini_merge的速度（默认值为3）。调大为8以后，发现会导致压测中CPU使用率有时飙升至90%，对性能有影响。
alter system set memory_limit_percentage = 90;    --  OB占系统总内存的比例，提高OB可用的内存量。
alter system set memstore_limit_percentage = 55;  --  memstore占租户的内存比，尽量增大memstore的空间（但是可能对读操作有负面影响）。
alter system set freeze_trigger_percentage = 40;  --  启动major/minor freeze的时机，让转储（minor freeze）尽早启动，memstore内存尽早释放。
alter system set minor_freeze_times = 100;        --  minor freeze的次数，尽量不在测试期间触发major freeze。
alter system set minor_warm_up_duration_time = 0;  --  加快minor freeze

```

OB 的 `oceanbasev10writer` 插件也提供参数 `memstoreThreshold` 监测增量内存的利用率，如果到达这个阈值，DataX 自动降速。

OB 的增量内存使用也可以监控，关键 SQL 是：

```sql
SELECT tenant_id, ip, round(active/1024/1024/1024) active_gb, round(total/1024/1024/1024) total_gb, round(freeze_trigger/1024/1024/1024) freeze_trg_gb, round(mem_limit/1024/1024/1024) mem_limit_gb
    , freeze_cnt , round((active/freeze_trigger),2) freeze_pct, round(total/mem_limit, 2) mem_usage
FROM `gv$memstore`
WHERE tenant_id =1001
ORDER BY tenant_id, ip;

```

OB 的监控产品里也能监控增量内存的变化。
