MySQL与Oracle场景下UPSERT对比常规INSERT/UPDATE预编译语句效率问询
UPSERT方案对比现有实现的优势
哪怕需要分别适配MySQL和Oracle两套语法,使用原生UPSERT语句也比你当前的实现方案效率更高,同时可靠性更强。
现有实现的问题
- 多一次IO开销:你现在的逻辑需要先调用
getId查询数据库判断ID是否存在,再执行写操作,总共两次数据库交互,多了一次网络往返开销,高并发场景下性能损耗非常明显。 - 存在并发安全问题:判断存在性和写操作是两个独立步骤,没有原子性保障,高并发场景下多个请求同时查询到同个ID不存在,同时执行插入会触发主键冲突异常,你当前的代码没有处理这类异常,会直接抛错。
- 代码冗余:需要分别维护插入、更新两套SQL的参数绑定逻辑,后期字段调整需要同时修改两处,容易出问题。
UPSERT的核心优势
- 性能更高:UPSERT是数据库原生提供的原子操作,只需要一次数据库交互就能完成判断+写的全流程,比现有实现少了一次网络请求,性能提升幅度至少在30%以上,跨机房部署的场景提升会更明显。
- 天然原子性:数据库层面保证操作的原子性,无需额外加锁或者加事务控制,不会出现并发冲突导致的主键插入报错问题。
- 代码更简洁:不需要提前做存在性查询,也不需要在业务代码里判断走插入还是更新逻辑,只需要绑定一次参数即可,后期维护成本更低。
两套数据库的语法参考
MySQL 语法(INSERT ON DUPLICATE KEY UPDATE)
INSERT INTO delivery (id, external_id, `desc`, url, response, created_date) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE url = VALUES(url), response = VALUES(response), created_date = VALUES(created_date);
注意:desc是MySQL关键字,需要用反引号转义,且id字段必须是主键或存在唯一索引,语法才能生效。
Oracle 语法(MERGE INTO)
MERGE INTO delivery d USING dual ON (d.id = ?) WHEN MATCHED THEN UPDATE SET d.url = ?, d.response = ?, d.created_date = ? WHEN NOT MATCHED THEN INSERT (id, external_id, "desc", url, response, created_date) VALUES (?,?,?,?,?,?);
注意:Oracle中关键字转义用双引号,参数绑定顺序为:id、更新用url/response/created_date、插入用id/external_id/desc/url/response/created_date。
内容的提问来源于stack exchange,提问作者Joerdan Devera
相关产品推荐
相关产品推荐

