Mysql批量更新的三种方式

前言

批量插入因为mysql的VALUES原生支持,使用较为便利。mysql

批量更新的写法通常有三种,在更新数量较少的状况下,前两种性能不相上下。可是在更新字段增长,更新条数较多(500以上)建议使用第三种写法。spring

  • 常规写法,拼接多个单条更新语句。
  • CASE...WHEN... 写法
  • JOIN 写法

Batch Update

spring/mybatis/JDBI都支持这种批量更新方式。 这种更新方式须要设置jdbc链接的参数:sql

allowMultiQueries=true
# 完整url举例
jdbc.url=jdbc:mysql://localhost:3306/db_name?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true

具体实现以Spring的JdbcTemplate为例。 batchUpdate的主要代码以下图: 数据库

首先检查了jdbc链接是否支持批量更新操做,若是allowMultiQueries值为false,将被拦截。 而后拼接了SQL语句,拼接代码以下:mybatis

直接用分号拼接。性能

CASE WHEN

示例:测试

UPDATE test
SET code = (
CASE 
WHEN id = 1 THEN 11
WHEN id = 2 THEN 22
WHEN id = 3 THEN 33
END
) WHERE id IN (1,2,3);

注意:CASE WHEN必定要和WHERE语句一块儿使用,不然UPDATE会遍历和更新数据库中全部的行。会把未出如今WHEN中的数据都更新成null,若是code列设置为NOT NULL则会报错,不然会置为NULL或者默认值。url

JOIN

这种写法不太常见。spa

UPDATE `test` a JOIN 
(
SELECT 1 AS id, 11 AS code, 'holy' AS name
UNION 
SELECT 2 AS id, 22 AS code, 'shit' AS name
) b USING(id, code)
SET a.name=b.name;

上述SQL要表达的更新语义是:将id=1且code=11的name更新为'holy',将id=2且code=22的name更新为'shit'。 注意,条件字段必须放在USINGcode

性能对比

RC隔离级别

更新条数小(通常小于500条),CASE WHENJOIN优于UDPATE。 更新条数较大(千级别),CASE WHEN效率迅速降低,UPDATE居中,推荐使用JOIN写法

RR隔离级别

JOIN性能优于CASE WHENCASE WHEN优于UPDATE

RC级别下的测试数据

数据库实例规格:8核,20G内存,100G硬盘 隔离级别:READ-COMMITTED 链接方式:JDBC

更新方式 更新300条记录平均耗时 更新3000条记录平均耗时
UPDATE 230ms 560ms
CASE WHEN 110ms 1170ms
JOIN 100ms 320ms
相关文章
相关标签/搜索