批量更新真的更快吗?批大小多少合适?MySQL 的 rewriteBatchedStatements 与 PostgreSQL 的 reWriteBatchedInserts 各有多大影响?一批里有一行出错时,已经成功的行算不算数?这篇用两个真实数据库逐项测。
逐行 executeUpdate,autocommit=true 932.2 ms 21456 行/秒 表中 20000 行 逐行 executeUpdate,autocommit=false,最后一次 commit 533.7 ms 37474 行/秒 表中 20000 行 addBatch / executeBatch,批大小 1 544.2 ms 36750 行/秒 表中 20000 行 批大小 10 108.2 ms 184829 行/秒 表中 20000 行 批大小 100 60.9 ms 328197 行/秒 表中 20000 行 批大小 1000 59.5 ms 335964 行/秒 表中 20000 行 批大小 10000 57.6 ms 347070 行/秒 表中 20000 行 批大小 20000(一次发完) 55.8 ms 358600 行/秒 表中 20000 行
逐行 executeUpdate,autocommit=true 924.4 ms 21635 行/秒 表中 20000 行 逐行 executeUpdate,autocommit=false,最后一次 commit 532.4 ms 37567 行/秒 表中 20000 行 addBatch / executeBatch,批大小 1 544.6 ms 36722 行/秒 表中 20000 行 批大小 10 87.9 ms 227591 行/秒 表中 20000 行 批大小 100 31.5 ms 634043 行/秒 表中 20000 行 批大小 1000 24.2 ms 824785 行/秒 表中 20000 行 批大小 10000 25.9 ms 771029 行/秒 表中 20000 行 批大小 20000(一次发完) 21.4 ms 933585 行/秒 表中 20000 行
逐行 executeUpdate,autocommit=true 1836.4 ms 10891 行/秒 表中 20000 行 逐行 executeUpdate,autocommit=false,最后一次 commit 679.2 ms 29447 行/秒 表中 20000 行 addBatch / executeBatch,批大小 1 1306.5 ms 15308 行/秒 表中 20000 行 批大小 10 718.0 ms 27855 行/秒 表中 20000 行 批大小 100 648.8 ms 30828 行/秒 表中 20000 行 批大小 1000 649.9 ms 30774 行/秒 表中 20000 行 批大小 10000 646.2 ms 30948 行/秒 表中 20000 行 批大小 20000(一次发完) 642.6 ms 31126 行/秒 表中 20000 行
逐行 executeUpdate,autocommit=true 1839.7 ms 10871 行/秒 表中 20000 行 逐行 executeUpdate,autocommit=false,最后一次 commit 691.0 ms 28945 行/秒 表中 20000 行 addBatch / executeBatch,批大小 1 1391.5 ms 14373 行/秒 表中 20000 行 批大小 10 183.3 ms 109115 行/秒 表中 20000 行 批大小 100 82.3 ms 243124 行/秒 表中 20000 行 批大小 1000 67.5 ms 296087 行/秒 表中 20000 行 批大小 10000 76.6 ms 261125 行/秒 表中 20000 行 批大小 20000(一次发完) 78.7 ms 254213 行/秒 表中 20000 行
批里第 3 行主键重复:autocommit=true,抛 BatchUpdateException;getUpdateCounts() 长度 5 = [-3, -3, -3, -3, -3];SQLState 23505
回滚 / 失败后表里的 id:3
批里第 3 行主键重复:autocommit=false,抛 BatchUpdateException;getUpdateCounts() 长度 5 = [-3, -3, -3, -3, -3];SQLState 23505
回滚 / 失败后表里的 id:3
成功的批:executeBatch() 返回 [1, 1](各行影响行数) 批里第 3 行主键重复:autocommit=true,抛 BatchUpdateException;getUpdateCounts() 长度 5 = [1, 1, -3, 1, 1];SQLState 23000
回滚 / 失败后表里的 id:1,2,3,4,5
批里第 3 行主键重复:autocommit=false,抛 BatchUpdateException;getUpdateCounts() 长度 5 = [1, 1, -3, 1, 1];SQLState 23000
回滚 / 失败后表里的 id:3
成功的批:executeBatch() 返回 [1, 1](各行影响行数) 批里第 3 行主键重复:autocommit=true,抛 BatchUpdateException;getUpdateCounts() 长度 2 = [1, 1];SQLState 23000
回滚 / 失败后表里的 id:1,2,3
批里第 3 行主键重复:autocommit=false,抛 BatchUpdateException;getUpdateCounts() 长度 2 = [1, 1];SQLState 23000
回滚 / 失败后表里的 id:3
成功的批:executeBatch() 返回 [1, 1](各行影响行数)