* 0.結論先行 * 1.背景介紹 * 2.測試過程 * 3.結果對比 - 附錄 > myloader還預設禁用binlog了 ## 0. 結論先行 重要結論先說:導入大批量數據時,採用GreatSQL 8.0.32-24中新增並行load data特性是最快的,關於該特性的描述詳見:[Change ...
- 0.結論先行
- 1.背景介紹
- 2.測試過程
- 3.結果對比
- 附錄
myloader還預設禁用binlog了
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 myload\G
*************************** 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 |
從這個測試結果可以看到幾個對比關係:
- 原生load data最慢,因為是單線程的,它的耗時是並行load data的5.32倍;
- 原生load data的耗時是多線程模式下myloader的2.14倍;
- 原生load data的耗時是多線程模式下util.importTable的3.92倍;
- 當myloader沒有開啟並行(mydumper備份時要先進行分配)的話,它的耗時是最久的,是並行load data的7倍,是多線程模式下util.importTable的5.16倍;
- 當myloader未開啟binlog時(其預設行為,有"作弊"嫌疑),其耗時是並行load data的1.81倍,是多線程模式下util.importTable的1.34倍;
- 最後,myloader導入後造成的binlog文件最大,記憶體開銷也最大。
綜上,在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, bytesPerChunk:"67108864"})
最後的(壓縮後)文件總大小為505MB。
Enjoy GreatSQL