mysql独有的高性能批量插入

INSERT INTO tracking_log(url,ip) VALUES('test1','test2'),('test2','test3'),('test2','test3'),('test2','test3')
### Java 实现数据存在更新、不存在新增的方法 在 Java 中实现数据的增删改查逻辑时,特别是在判断数据是否存在后进行更新或新增的操作,可以通过多种方式实现。以下是基于提供的引用内容以及专业知识的具体说明。 #### 使用 JDBC 和 SQL 的 ON DUPLICATE KEY UPDATE 语句 MySQL 提供了一种高效的解决方案——`ON DUPLICATE KEY UPDATE`[^3]。该语法允许在插入新记录时检测到唯一索引冲突的情况下自动触发更新操作。这种方式适用于 MySQL 数据库环境下的场景: ```sql INSERT INTO table_name (column1, column2, column3) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE column1=VALUES(column1), column2=VALUES(column2); ``` 通过上述 SQL 语句,在 Java 中可以利用 `PreparedStatement` 来动态绑定参数并执行此操作: ```java String sql = "INSERT INTO table_name (id, name, value) VALUES (?, ?, ?)" + "ON DUPLICATE KEY UPDATE name=VALUES(name), value=VALUES(value)"; try (Connection conn = DriverManager.getConnection(url, username, password); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setInt(1, id); // 主键或其他唯一约束字段 pstmt.setString(2, name); pstmt.setDouble(3, value); int rowsAffected = pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e.getMessage()); } ``` 这种方法的优点在于它减少了多次查询数据库的需求,从而提高了性能。 #### 法一:先查询再决定更新还是插入 另一种常见的做法是在应用程序层面控制逻辑流程。即先尝试从数据库读取目标记录,如果找到对应的记录,则调用更新方法;反之则发起插入请求[^2]。 ```java public void upsertData(Connection connection, MyEntity entity) throws SQLException { String selectSql = "SELECT * FROM my_table WHERE unique_key_column=?"; try (PreparedStatement selectStmt = connection.prepareStatement(selectSql)) { selectStmt.setString(1, entity.getUniqueKey()); ResultSet rs = selectStmt.executeQuery(); if (!rs.next()) { // 如果未匹配任何行,则表示需插入新的条目 insertRecord(connection, entity); } else { // 否则应该更新现有项的内容 updateRecord(connection, entity); } } } private void insertRecord(Connection connection, MyEntity entity) throws SQLException { String insertSql = "INSERT INTO my_table (unique_key_column, colA, colB) VALUES (?, ?, ?)"; try (PreparedStatement stmt = connection.prepareStatement(insertSql)) { stmt.setString(1, entity.getUniqueKey()); stmt.setString(2, entity.getColumnA()); stmt.setString(3, entity.getColumnB()); stmt.executeUpdate(); } } private void updateRecord(Connection connection, MyEntity entity) throws SQLException { String updateSql = "UPDATE my_table SET colA=?, colB=? WHERE unique_key_column=?"; try (PreparedStatement stmt = connection.prepareStatement(updateSql)) { stmt.setString(1, entity.getColumnA()); stmt.setString(2, entity.getColumnB()); stmt.setString(3, entity.getUniqueKey()); stmt.executeUpdate(); } } ``` 尽管这种方案较为直观易懂,但它涉及两次独立访问数据库的动作(一次 SELECT 查询加一次 INSERT/UPDATE),因此可能带来额外开销。 #### 法二:引入批次号机制简化操作 为了进一步提升效率,还可以采用批量处理的方式。具体而言,可以在每次导入前分配一个新的批次编号给待同步的数据集,并据此区分哪些是最新版本的有效数据,而无需逐一核验每一条单独记录的状态变化情况[^1]。 假设当前表结构如下所示: | batch_no | key_col | data_value | |----------|---------|------------| | A001 | K001 | Value_1 | 当接收到一批新的输入源之后,只需简单地比较旧有批次与传入批次之间的差异即可得出结论: - 对于那些仅存在于后者中的项目来说意味着它们应当被加入; - 而同时出现在两者里的部分代表其属性发生了改变所以需要覆盖原值; - 至于前者独有的成分自然属于过期淘汰对象故应予以移除。 最终形成的SQL脚本大致形式如下所列: ```sql -- 删除不属于本次上传范围内的历史残留物 DELETE FROM target_table WHERE batch_no != 'current_batch'; -- 插入所有来自临时存储区的新成员 INSERT INTO target_table(batch_no, key_col, data_value) SELECT 'current_batch', t.key_col, t.data_value FROM staging_area AS t LEFT JOIN target_table tt USING(key_col) WHERE tt.batch_no IS NULL OR tt.batch_no <> 'current_batch'; ``` 以上述代码为例展示了如何借助中间过渡区域完成整个过程的同时保持较高的吞吐率水平[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值