关于tidb:TiDB-750-LTS-高性能数据批处理方案

8次阅读

共计 4552 个字符,预计需要花费 12 分钟才能阅读完成。

过来,TiDB 因为不反对存储过程、大事务的应用也存在一些限度,使得在 TiDB 上进行一些简单的数据批量解决变得比较复杂。

TiDB 在面向这种超大规模数据的批处理场景,其能力也始终在演进,其复杂度也变得越来越低:

○ 从 TiDB 5.0 开始,TiFlash 反对 MPP 并行计算能力,在大批量数据上进行聚合、关联的查问性能有了极大的晋升

○ 到了 TiDB 6.1 版本,引入了 BATCH DML (https://docs.pingcap.com/zh/tidb/stable/non-transactional-dml) 性能,该性能能够将一个大事务主动拆成多个批次去解决,在单表根底上进行大批量更新、删除、写入时可能大幅晋升解决效率,同时防止了大事务所产生的一些影响。

○ 而到了 7.1 LTS 版本,正式 GA 了 TiFlash 查问后果物化 (https://docs.pingcap.com/zh/tidb/stable/tiflash-results-mater… 查问后果物化) 的性能,使得 insert/replace into … select … 这种操作中的简单 select 可能利用 TiFlash MPP 并行处理的能力,大幅晋升了这种操作的解决性能。

○ 前不久刚公布的 7.5 LTS,正式 GA 了一个 IMPORT INTO (https://docs.pingcap.com/zh/tidb/stable/sql-statement-import-…) 的性能,该性能将本来 tidb-lightning 的物理导入能力集成到 TiDB 计算节点上,应用一条 SQL 语句就能够实现大批量数据的导入,大幅简化了超大规模数据写入时的复杂度。

TiDB 上之前有哪些批处理计划

  1. INSERT INTO … SELECT 实现查问和写入

● 现状:实用于小批量数据处理,性能较高

● 挑战:大批量数据写入时,会产生大事务,耗费内存较高

阐明:写入 + 单表查问场景可应用 BATCH DML 性能主动拆批

  1. 针对 INSERT INTO/INSERT INTO … ON DUPLICATE …/REPLACE INTO 这些 SQL 应用批量接口执行,升高利用与数据库之间的交互次数,晋升批量写入时的性能

● 现状:在适合的拆批计划、表结构设计上,解决性能十分高

● 挑战:编码不合理、表结构设计不合理时,可能会遇到热点问题,导致性能不佳

  1. 通过 ETL 和调度平台提供的数据读取和写入能力实现大批量数据的解决

● 现状:支流的 ETL 平台,如 datax、spark、kettle 等,在正当表结构设计时,性能也比拟高

● 挑战:多线程并行写入时,也有可能会遇到热点问题

  1. 针对上游传过来的 csv 文件的数据,应用 LOAD DATA 来实现批量数据的写入,晋升批量写入时的性能

● 现状:在对文件进行拆分 + 多线程并行后,解决性能十分高

● 挑战:当 LOAD DATA 一个大文件时此时是大事务,导致性能不佳;多线程解决时也有可能遇到热点问题,导致性能不佳

针对以上几种批处理计划,以及最新推出的 IMPORT INTO 性能,咱们发展了一次测试,摸索哪种批处理计划效率最高,耗费资源更低,以及应用上更加简略。

TiDB 中不同批处理计划的测试

1 测试环境

  1. TiDB 资源:3 台 16VC/64GB 虚拟机 + 500GB SSD 云盘(3500 IOPS + 250MB/S 读写带宽)

a. TiDB 版本:TiDB V7.5.0 LTS

b. TiDB 组件:TiDB/PD/TiKV/TiFlash(混合部署)

  1. 存储资源:8C/64GB 虚拟机 + 500GB SSD 云盘(3500 IOPS + 250MB/S 读写带宽)

● 存储服务:NFS 服务、Minio 对象存储

  1. 测试资源:8C/64GB 虚拟机 + 500GB SSD 云盘(3500 IOPS + 250MB/S 读写带宽)

● datax + Dolphin 调度 /java 程序 /dumpling、tidb-lightning 工具以及 MySQL 客户端

2 测试场景

将大批量查问后果疾速写入到指标表,既考验查问性能,同时也考验批量写入的性能。

2.1 查问局部:多表关联 + 聚合

基于 TPCH 100GB 数据,扩大 Q10 查问中的字段和查问范畴,返回 8344700 行数据。

select  c_custkey,c_name,sum(l_extendedprice * (1 - l_discount)) as revenue,
        c_acctbal,n_name,c_address,c_phone,c_comment,min(C_MKTSEGMENT),min(L_PARTKEY), 
        min(L_SUPPKEY,min(L_LINENUMBER),min(L_QUANTITY), max(L_TAX), max(L_LINESTATUS), 
        min(L_SHIPDATE), min(L_COMMITDATE), min(L_RECEIPTDATE), min(L_SHIPINSTRUCT), 
        max(L_SHIPMODE), max(O_ORDERSTATUS), min(O_TOTALPRICE), min(O_ORDERDATE), 
        max(O_ORDERPRIORITY), min(O_CLERK), max(O_SHIPPRIORITY), 
        @@hostname as etl_host,current_user() as etl_user,current_date() as etl_date
from
        tpch.customer,tpch.orders,tpch.lineitem,tpch.nation
where
        c_custkey = o_custkey and l_orderkey = o_orderkey
        and o_orderdate >= date '1993-10-01' and o_orderdate < date '1994-10-01'
        and l_returnflag = 'R' and c_nationkey = n_nationkey
group by
        c_custkey,c_name,c_acctbal,c_phone,n_name,c_address,c_comment
order by c_custkey;

源表数据量

2.2 写入:29 列,1 个主键 +2 个索引

CREATE TABLE `tpch_q10` (`c_custkey` bigint(20) NOT NULL,
  `c_name` varchar(25) DEFAULT NULL,
  `revenue` decimal(15,4) DEFAULT NULL,
   ...
  `etl_host` varchar(64) DEFAULT NULL,
  `etl_user` varchar(64) DEFAULT NULL,
  `etl_date` date DEFAULT NULL,
  PRIMARY KEY (`c_custkey`) /*T![clustered_index] CLUSTERED */,
  KEY `idx_orderdate` (`o_orderdate`),
  KEY `idx_phone` (`c_phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

3 测试后果

4 测试剖析

4.1 JAVA 程序应用 SQL 进行批处理

应用 JAVA 解决时,StreamingResult 流式读取 + 多并发写入形式可能取得十分好的性能。强烈不倡议应用 limit 分页这种模式拆批,这种逻辑数据库将执行 844 条查问 SQL,效率极低,耗费的资源极高。同时 StreamingResult 这种流式读取还能够应用于数据导出的场景,比照应用 limit 分页解决,效率也更高。

在程序 4 中,将本来查问 SQL 里的 order by c_custkey 换成了 order by revenue desc 后,对性能也有肯定影响,起因次要是多线程写入时 RPC 开销重大放大。

在程序 5 中,将本来查问 SQL 中的 c_phone 换成 ‘132-0399-0111’ as c_phone,模仿索引热点。

4.2 LOAD DATA 形式

如果应用 LOAD DATA 要取得比拟高的性能,倡议对单个文件进行拆分,同时 csv 中文件的程序倡议与指标表主键程序统一,如一个 CSV 文件存储 20000 行,再通过多线程并行来写入,此时写入性能也比拟高。

如果仅 LOAD DATA 导入单个大文件,那么性能较低,且耗费内存较高。

4.3 ETL+ 调度平台形式

作业类型:datax(mysqlreader + mysqlwriter),简略,效率个别

调度平台执行 datax 作业:应用 mysqlreader 形式读取时,默认就应用流式读取,然而对于多表查问的 query 时,写入时无奈并发

作业类型:shell + datax(txtfileread + mysqlwriter),较简单,效率较高

调度平台执行 shell:应用 dumpling 导出成多个 csv 文件

再调度 datax 作业:应用 txtfilereader + mysqlwriter,此时能够多线程并发写入,效率较高

作业类型:SQL,简略高效

调度平台执行 SQL:select … into outfile

调度平台执行 SQL:import into

4.4 SELECT … INTO OUTFILE 导出查问后果(以后仅反对导出到文件系统)

该性能大家平时可能应用比拟少,但该性能十分有价值,它能够高效的将数据一批导出、并且数据是完全一致的状态,能够用于:

a. 批量数据处理:JAVA 程序可间接执行该 SQL 实现后果的导出

b. 在简略的数据导出场景,应用导出 csv 替换本来 limit 解决逻辑,利用将查问后果导出到一个共享 NFS/S3 对象存储中,再读取 NFS/S3 对象存储中的 CSV,进行后果的解决,极大的升高了数据库的压力,同时性能将比之前应用 limit 分批解决更高。

4.5 IMPORT INTO 导入 CSV(以后反对 S3 协定对象存储以及文件系统)

该性能 7.5.0 引入,极大的简化了数据导入的难度,JAVA 程序可间接执行该 SQL 实现 CSV 数据的导入,在进行批处理时利用节点简直不须要耗费 CPU/ 内存资源。以下是应用示例:

IMPORT INTO test.tpch_q10 FROM '/mnt/nfs/test.tpch_q10.csv' with FIELDS_TERMINATED_BY='\t',split_file,thread=8;

须要留神的是:IMPORT INTO 导入过程中,不会产生日志,所以针对须要 CDC 同步或 Kafka 散发的场景,该计划不实用。

5 测试小结

局部测试代码示例:https://github.com/Bowen-Tang/batch-samples

总结与瞻望

TiDB 7.5.0 引入的 IMPORT INTO 性能,联合 SELECT … INTO OUTFILE、以及 NFS/ 对象存储,让 TiDB 上减少了一种更加简略且十分高效的批处理计划,JAVA 利用程序处理时更加简略,ETL 调度也更简略。

以下是 TiDB 应用 IMPORT INTO、SELECT … INTO OUTFILE 的架构示例:

I MPORT INTO 性能以后仅反对 CSV 导入,将来 TiDB 8.x 版本中 IMPORT INTO 将间接集成 IMPORT INTO … SELECT … 性能,极致简化批处理操作,性能也更进一步晋升(187 秒),敬请大家期待:

正文完
 0