0. 结论先行
重要结论先说:导入大批量数据时,采用GreatSQL 8.0.32-24中新增并行load data特性是最快的,关于该特性的描述详见:Changes in GreatSQL 8.0.32-24。
1. 背景介绍
前几天我用MySQL官网提供的airportdb库中的weatherdata表做测试,结论是相比原生快了约5倍。
群里有小伙伴反驳说用myloader更香,于是就有了本次测试。
由于weatherdata表较小,表空间只有228MB,所以我改用sysbench表做测试,该表共600万行数据,表空间约1.5GB,其他信息如下:
greatsql> show create table myloadG
*************************** 1. row ***************************
Table: myload
Create Table:CREATE TABLE `myload` (
`id` int NOT NULL AUTO_INCREMENT,
`k` int NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_2` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=6194244 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
greatsql> show table status like 'myload'G
*************************** 1. row ***************************
Name: myload
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 5930876
Avg_row_length: 233
Data_length: 1385168896
Max_data_length: 0
Index_length: 153894912
Data_free: 7340032
Auto_increment: 6194244
Create_time: 2023-07-08 09:25:02
Update_time: 2023-07-08 09:25:33
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
2. 测试过程
本次测试基于GreatSQL 8.0.32-24版本,其他相关信息如下:
# myloader版本
$ myloader --version
myloader0.15.0-1, built against MySQL 5.7.42-46 with SSL support with GZIP
# MySQL Shell版本
JS > shell.version
Ver 8.0.32 for Linux on x86_64 - for MySQL 8.0.32 (MySQL Community Server (GPL))
默认开启binlog + 双1 + redo log + doublewrite buffer:
|binlog_rows_query_log_events |ON|
| innodb_buffer_pool_size | 8589934592|innodb_doublewrite |ON|
|innodb_flush_log_at_trx_commit |1|
|innodb_redo_log_capacity |2147483648|
|sync_binlog |1|
3. 结果对比
下面是几个不同导入方式的对比测试结果,每种方式我都测试至少3次,去除噪点数据后取平均值:
工具 |
耗时(秒) |
binlog大小(MB) |
mysqld内存增长(MB) |
原生load data |
62.801741 |
1091 |
1536 |
并行load data(chunk=4MB,并发16线程) |
11.81 |
1091 |
1522 |
myloader(dump时chunk=64MB,load时并发16线程) |
29.358 |
2246 |
1868 |
myloader(dump时chunk=64MB,load时并发16线程)+ 关binlog |
21.426 |
无 |
|
myloader(默认 + 开binlog) |
82.651 |
2246 |
|
myloader(默认 + 关binlog) |
62.830 |
无 |
|
util.importTable(默认,chunk=64MB,并发8线程) |
16.0034 |
1091 |
1662 |
从这个测试结果可以看到几个对比关系:
图片
综上,在MySQL 8.0/GreatSQL 8.0.32中,采用myloader导入数据就不再是最优方案了,推荐采用GreatSQL的并行load data,或者MySQL Shell的util.loadDump/util.importTable导入,其本质也是采用并行的思路,导入效率更高,额外的binlog和内存开销也更小。
最后,补充说下,myloader导入时产生的binlog更多,是因为它的导入方式是反复执行INSERT SQL,在 binlog_rows_query_log_events = ON 时,相比load data方式会产生更多binlog。
附录
1. myloader多分片方式导出
设置导出时进行分片,每个分片(chunk)10MB
$ mydumper -F 10 -S /data/GreatSQL/mysql.sock -T sbtest.myload -o /tmp/myload
最后的(未压缩)文件总大小为1.2GB。
2. outfile导出
greatsql> select * into outfile '/tmp/myload.csv' from myload;
很简单,平平无奇,最后的(未压缩)文件总大小为1.1GB。
3. util.dumpTables多分片方式导出 设置导出时进行分片,每个分片(chunk)64MB(默认值)
MySQL localhost JS > util.dumpTables("sbtest", ["myload"], "/tmp/myload", {threads:16, chunking:true, byt