测试环境:.NET 10 + MySQL 8.0.26 本机(Windows),Stopwatch 计时,每方案预热 1 轮 + 测量 3 轮取中位数。
1. 批量方案对比(--quick)
对比 NewLife.MySql 内置的多种批量操作方案在 INSERT/UPDATE/DELETE 三种操作下的性能。
1.1 INSERT
耗时(中位数 ms)
方案 | 类别 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow INSERT | baseline | 35.72 | 437.20 | 3,150.36 |
ExecuteBatch | serial | 31.51 | 264.36 | 2,657.24 |
ExecuteArrayBatch | serial | 36.79 | 227.03 | 2,647.68 |
ExecuteBatch+Pipeline | pipeline | 22.91 | 98.09 | 1,262.50 |
ExecuteArrayBatch+Pipeline | pipeline | 21.67 | 108.48 | 1,115.60 |
Multi-row VALUES | text | 3.84 | 20.78 | 144.76 |
DbBatch API | text | 19.35 | 215.45 | 1,232.86 |
SingleRow INSERT (tx) | tx | 39.97 | 255.86 | 2,482.99 |
ExecuteBatch (tx) | tx | 32.53 | 167.37 | 1,874.76 |
ExecuteArrayBatch (tx) | tx | 30.79 | 188.85 | 1,915.66 |
ExecuteBatch+Pipeline (tx) | tx+pipe | 17.90 | 73.11 | 779.09 |
ExecuteArrayBatch+Pipeline (tx) | tx+pipe | 12.76 | 53.85 | 680.25 |
加速比(vs SingleRow INSERT 基线)
方案 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow INSERT | 1.0x | 1.0x | 1.0x |
ExecuteBatch | 1.1x | 1.7x | 1.2x |
ExecuteArrayBatch | 1.0x | 1.9x | 1.2x |
ExecuteBatch+Pipeline | 1.6x | 4.5x | 2.5x |
ExecuteArrayBatch+Pipeline | 1.6x | 4.0x | 2.8x |
Multi-row VALUES | 9.3x | 21.0x | 21.8x |
DbBatch API | 1.8x | 2.0x | 2.6x |
SingleRow INSERT (tx) | 0.9x | 1.7x | 1.3x |
ExecuteBatch (tx) | 1.1x | 2.6x | 1.7x |
ExecuteArrayBatch (tx) | 1.2x | 2.3x | 1.6x |
ExecuteBatch+Pipeline (tx) | 2.0x | 6.0x | 4.0x |
ExecuteArrayBatch+Pipeline (tx) | 2.8x | 8.1x | 4.6x |
INSERT 分析
- Multi-row VALUES 最快:将多行数据拼成一条
INSERT ... VALUES (...), (...), ...SQL,只需一次网络往返和一次 SQL 解析,10,000 行仅 145ms(21.8x 加速)。缺点是只适用于 INSERT,且需手动拼接 SQL、注意注入风险。
- 管道化+事务(tx+pipe) 是参数化方案中的最优组合:
ExecuteArrayBatch+Pipeline (tx)在 1,000 行达到 8.1x 加速(53.85ms vs 437.20ms),10,000 行达到 4.6x 加速(680ms vs 3,150ms)。
- 原理:事务将多条 DML 合并为一次磁盘刷写(group commit),管道化将 N 次网络往返压缩为 1 次批量发送+1 次批量接收。
- 串行预编译(serial) 在小批量(100 行)几乎无优势,数据量增大后提升到 1.2x~1.9x。原因是串行模式下每条仍需独立的发送-等待-接收循环,瓶颈在网络往返而非 SQL 解析。
- DbBatch API 走文本协议多语句(
;分隔),性能在 2.0x~2.6x 之间,介于串行和管道化之间。
1.2 UPDATE
耗时(中位数 ms)
方案 | 类别 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow UPDATE | baseline | 49.05 | 347.10 | 3,469.46 |
ExecuteBatch UPDATE | serial | 29.74 | 258.42 | 2,780.43 |
ExecuteArrayBatch UPDATE | serial | 30.73 | 256.43 | 2,899.72 |
ExecuteBatch+Pipeline UPDATE | pipeline | 19.76 | 128.00 | 1,315.29 |
ExecuteArrayBatch+Pipeline UPDATE | pipeline | 21.56 | 202.22 | 1,361.31 |
Multi-stmt UPDATE | text | 18.05 | 206.42 | 1,632.29 |
DbBatch UPDATE | text | 10.90 | 242.23 | 1,572.31 |
SingleRow UPDATE (tx) | tx | 33.83 | 268.87 | 2,672.09 |
ExecuteBatch UPDATE (tx) | tx | 23.69 | 240.24 | 2,082.73 |
ExecuteArrayBatch UPDATE (tx) | tx | 24.41 | 270.85 | 2,068.29 |
ExecuteBatch+Pipeline UPDATE (tx) | tx+pipe | 14.42 | 150.78 | 756.90 |
ExecuteArrayBatch+Pipeline UPDATE (tx) | tx+pipe | 16.84 | 75.11 | 792.91 |
加速比(vs SingleRow UPDATE 基线)
方案 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow UPDATE | 1.0x | 1.0x | 1.0x |
ExecuteBatch UPDATE | 1.6x | 1.3x | 1.2x |
ExecuteArrayBatch UPDATE | 1.6x | 1.4x | 1.2x |
ExecuteBatch+Pipeline UPDATE | 2.5x | 2.7x | 2.6x |
ExecuteArrayBatch+Pipeline UPDATE | 2.3x | 1.7x | 2.5x |
Multi-stmt UPDATE | 2.7x | 1.7x | 2.1x |
DbBatch UPDATE | 4.5x | 1.4x | 2.2x |
SingleRow UPDATE (tx) | 1.4x | 1.3x | 1.3x |
ExecuteBatch UPDATE (tx) | 2.1x | 1.4x | 1.7x |
ExecuteArrayBatch UPDATE (tx) | 2.0x | 1.3x | 1.7x |
ExecuteBatch+Pipeline UPDATE (tx) | 3.4x | 2.3x | 4.6x |
ExecuteArrayBatch+Pipeline UPDATE (tx) | 2.9x | 4.6x | 4.4x |
UPDATE 分析
- 管道化+事务(tx+pipe) 依然是最优方案,10,000 行 UPDATE 达到 4.4x~4.6x 加速(757ms~793ms vs 3,469ms)。
- UPDATE 的加速比整体高于 INSERT。原因:UPDATE 需要先通过索引查找目标行再修改,单行操作的 InnoDB 行锁和 redo log 刷写开销更大,事务合并的收益更显著。
- 纯管道化(pipeline) 不加事务时 10,000 行加速 2.5x~2.6x,说明管道化本身消除了网络延迟瓶颈,但没有事务的 group commit 优化,磁盘 IO 仍是瓶颈。
1.3 DELETE
耗时(中位数 ms)
方案 | 类别 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow DELETE | baseline | 32.36 | 332.17 | 3,350.69 |
ExecuteBatch DELETE | serial | 24.62 | 322.70 | 2,783.21 |
ExecuteArrayBatch DELETE | serial | 30.12 | 286.85 | 2,846.77 |
ExecuteBatch+Pipeline DELETE | pipeline | 17.90 | 124.07 | 1,648.73 |
ExecuteArrayBatch+Pipeline DELETE | pipeline | 23.01 | 120.45 | 1,377.27 |
IN() DELETE | text | 1.15 | 5.48 | 78.43 |
DbBatch DELETE | text | 23.49 | 110.26 | 1,636.00 |
SingleRow DELETE (tx) | tx | 27.43 | 275.01 | 2,445.99 |
ExecuteBatch DELETE (tx) | tx | 17.63 | 239.00 | 1,945.07 |
ExecuteArrayBatch DELETE (tx) | tx | 17.54 | 205.36 | 1,916.83 |
ExecuteBatch+Pipeline DELETE (tx) | tx+pipe | 15.89 | 51.82 | 803.85 |
ExecuteArrayBatch+Pipeline DELETE (tx) | tx+pipe | 9.46 | 78.83 | 673.32 |
加速比(vs SingleRow DELETE 基线)
方案 | 100 行 | 1,000 行 | 10,000 行 |
SingleRow DELETE | 1.0x | 1.0x | 1.0x |
ExecuteBatch DELETE | 1.3x | 1.0x | 1.2x |
ExecuteArrayBatch DELETE | 1.1x | 1.2x | 1.2x |
ExecuteBatch+Pipeline DELETE | 1.8x | 2.7x | 2.0x |
ExecuteArrayBatch+Pipeline DELETE | 1.4x | 2.8x | 2.4x |
IN() DELETE | 28.1x | 60.6x | 42.7x |
DbBatch DELETE | 1.4x | 3.0x | 2.0x |
SingleRow DELETE (tx) | 1.2x | 1.2x | 1.4x |
ExecuteBatch DELETE (tx) | 1.8x | 1.4x | 1.7x |
ExecuteArrayBatch DELETE (tx) | 1.8x | 1.6x | 1.7x |
ExecuteBatch+Pipeline DELETE (tx) | 2.0x | 6.4x | 4.2x |
ExecuteArrayBatch+Pipeline DELETE (tx) | 3.4x | 4.2x | 5.0x |
DELETE 分析
- IN() DELETE 断崖式领先:
DELETE FROM t WHERE id IN (1,2,...,N)将 N 条删除合并为一条 SQL,1,000 行仅 5.48ms(60.6x 加速),10,000 行仅 78ms(42.7x 加速)。原理:一次 SQL 解析+一次 B+Tree 扫描+一次 redo log 提交,效率远超逐行删除。适合按主键批量清理的场景。
- 管道化+事务(tx+pipe) 在参数化方案中表现最优:10,000 行 DELETE 达到 5.0x 加速(673ms vs 3,351ms),是三种 DML 操作中加速比最高的。
- DELETE 的管道化加速比高于 INSERT/UPDATE,原因:DELETE 操作的 InnoDB 标记删除+清理回收开销较大,事务批量提交的 group commit 收益更明显。
2. 三驱动对比(--driver)
对比 NewLife.MySql、MySql.Data(Oracle 官方)、MySqlConnector 三个驱动在增删改查中的性能。
每个驱动测试两种模式:
- SingleRow:逐行参数化执行,体现驱动的基础协议效率
- 批量模式:NewLife 使用 Pipeline+事务+数组绑定,Official/Connector 使用事务+Prepare+循环执行
2.1 INSERT
驱动 | 100 行 | 1,000 行 | 10,000 行 |
NewLife SingleRow | 35.87 | 364.18 | 3,462.06 |
NewLife Pipeline(tx) | 13.35 | 82.24 | 899.39 |
Official SingleRow | 59.75 | 407.48 | 3,552.61 |
Official Batch(tx) | 43.65 | 249.16 | 1,927.27 |
Connector SingleRow | 57.22 | 349.37 | 2,820.83 |
Connector Batch(tx) | 30.24 | 210.21 | 1,905.96 |
分析:
- NewLife Pipeline(tx) 全面领先:10,000 行 INSERT 仅 899ms,比 Official Batch(tx) 快 2.1x,比 Connector Batch(tx) 快 2.1x。
- 逐行模式下,NewLife 与 Connector 接近,均优于 Official(Official 的 sync-over-async 实现有额外开销)。
- NewLife 的管道化优势在大数据量下越发明显:100 行 1.6x -> 1,000 行 2.6x -> 10,000 行 2.1x(vs 竞品最佳批量方案)。
2.2 SELECT
驱动 | 100 行 | 1,000 行 | 10,000 行 |
NewLife SingleRow | 35.54 | 300.53 | 2,827.41 |
Official SingleRow | 58.81 | 392.76 | 2,610.22 |
Connector SingleRow | 34.18 | 202.59 | 2,027.24 |
分析:
- SELECT 目前仅测试逐行查询模式(每次
SELECT ... WHERE id=@id),无批量查询 API。
- 小数据量(100~1,000 行)NewLife 与 Connector 接近,均显著优于 Official。
- 大数据量(10,000 行)Connector 领先,得益于其高度优化的结果集解析和内存管理。
- NewLife 在 SELECT 场景还有优化空间,后续可考虑结果集预读、批量 IN 查询等优化。
2.3 UPDATE
驱动 | 100 行 | 1,000 行 | 10,000 行 |
NewLife SingleRow | 43.48 | 326.81 | 3,284.16 |
NewLife Pipeline(tx) | 8.93 | 63.35 | 710.25 |
Official SingleRow | 53.13 | 333.22 | 3,207.52 |
Official Batch(tx) | 32.77 | 202.64 | 2,265.35 |
Connector SingleRow | 30.90 | 273.72 | 3,024.58 |
Connector Batch(tx) | 21.92 | 201.72 | 2,040.96 |
分析:
- NewLife Pipeline(tx) 断崖式领先:10,000 行 UPDATE 仅 710ms,比 Official Batch(tx) 快 3.2x,比 Connector Batch(tx) 快 2.9x。
- 1,000 行 UPDATE 的加速更为惊人:63ms vs 202ms(Official/Connector),3.2x 加速。
- 管道化在 UPDATE 场景的优势最为显著,因为 UPDATE 的单行开销(索引查找+行锁+redo log)比 INSERT 更大,管道化+事务的 group commit 收益更高。
2.4 DELETE
驱动 | 100 行 | 1,000 行 | 10,000 行 |
NewLife SingleRow | 36.10 | 411.18 | 3,341.81 |
NewLife Pipeline(tx) | 6.51 | 57.99 | 660.94 |
Official SingleRow | 26.10 | 279.88 | 3,345.19 |
Official Batch(tx) | 27.91 | 146.16 | 1,960.89 |
Connector SingleRow | 32.16 | 327.03 | 3,024.00 |
Connector Batch(tx) | 30.74 | 173.81 | 1,766.61 |
分析:
- NewLife Pipeline(tx) 再次全面领先:10,000 行 DELETE 仅 661ms,比 Official Batch(tx) 快 3.0x,比 Connector Batch(tx) 快 2.7x。
- 1,000 行 DELETE 中 NewLife Pipeline(tx) 仅 58ms,Official/Connector 最快也要 146ms/174ms,2.5x~3.0x 加速。
- DELETE 是管道化优势最大的场景:InnoDB 标记删除+清理回收+undo log 维护的开销大,事务 group commit 将 N 次磁盘刷写合并为 1 次。
3. 性能亮点总结
3.1 管道化+事务:参数化批量操作的王者
操作 | 10,000 行耗时 | vs 逐行基线 | vs 竞品最佳批量 |
INSERT | 680ms | 4.6x | 2.1x |
UPDATE | 710ms | 4.6x | 2.9x |
DELETE | 661ms | 5.0x | 2.7x |
核心原理:
- 管道化(Pipeline):批量发送所有 COM_STMT_EXECUTE 请求包后再批量读取响应,N 次网络往返压缩为 1 次。TCP 协议栈的 Nagle 算法自动合并小包为大包,减少系统调用。
- 事务(Transaction):InnoDB 的 group commit 机制将事务内所有 DML 的 redo log 合并为一次磁盘刷写,消除了逐行操作的 fsync 瓶颈。
- 预编译(Prepare):SQL 只解析一次,后续执行走二进制协议,参数以原生类型传输,减少 SQL 解析和字符串转换开销。
三者叠加,在本机低延迟环境已实现 4x~5x 加速。跨机房高延迟场景(如 1ms RTT),管道化的网络收益将更加显著(理论上可达 10x~50x)。
3.2 方案选型建议
场景 | 推荐方案 | 预期加速 |
纯 INSERT 批量(ETL/数据导入) | Multi-row VALUES 拼接 | 20x+ |
按主键批量 DELETE(数据清理) | IN() 条件删除 | 40x+ |
通用批量 DML(参数化,防注入) | ExecuteArrayBatch + Pipeline + 事务 | 4x~8x |
混合 SQL 批量(不同语句) | DbBatch API | 2x~3x |
小批量(< 100 行) | 逐行执行或事务包裹即可 | - |
3.3 NewLife.MySql vs 竞品驱动
维度 | NewLife.MySql | MySql.Data (Official) | MySqlConnector |
逐行 INSERT 性能 | ★★★★ | ★★★ | ★★★★ |
批量 INSERT 性能 | ★★★★★ | ★★★ | ★★★ |
批量 UPDATE 性能 | ★★★★★ | ★★★ | ★★★ |
批量 DELETE 性能 | ★★★★★ | ★★★ | ★★★ |
SELECT 查询性能 | ★★★ | ★★★ | ★★★★ |
管道化支持 | ✅ 独创 | ❌ | ❌ |
数组绑定 API | ✅ | ❌ | ❌ |
NewLife.MySql 在批量写入场景(INSERT/UPDATE/DELETE)凭借管道化+事务组合全面领先竞品 2x~3x;SELECT 场景与 Connector 接近,略优于 Official。
附录:测试方法说明
- 测试工具:Benchmark 项目,
dotnet run -c Release -- --quick/--driver
- 计时方式:
System.Diagnostics.Stopwatch,每方案预热 1 轮 + 测量 3 轮取中位数
- 数据量级:100 / 1,000 / 10,000 行
- 测试表结构:
bench_users/bench_driver(BIGINT PK + VARCHAR + INT + VARCHAR + DOUBLE + DATETIME)
- 环境:Windows 本机,MySQL 8.0.26,.NET 10 Release 模式
- 连接:TCP 127.0.0.1:3306,无 SSL,默认连接池