场景:主表为客户表,每天都需要从另外5张中间表里匹配到对应客户的信息,将其更新到客户表
使用的数据库为oracle,目前使用的做法是“update set select from left join ....”的方式
特殊情况:客户表里,客户编号是主键,但是在其他5张表里客户编号不是,所以在进行关联查询时,每张表都以客户编号,做了开窗操作,做到随机取一条
目前优化:将另外的5张表里,和主表匹配不到的数据将其全部删除,然后再开始跑更新逻辑;且做关联的字段都已加了索引
想咨询下各位大佬,在sql层面,有更好的优化方案吗?或者如果要修改为java代码的方式,在代码层面上有其他优化的方案吗?
在Oracle中,UPDATE SET子句通常用于在一个查询中更新多个列。然而,这种方法并不高效,因为它会导致多次扫描和处理每个结果集。此外,UPDATE SET子句还受到SQL规范中的限制,即不能直接使用JOIN语句。
一种替代方法是在Java代码中执行这些操作。这样可以避免多次扫描和处理每个结果集的问题,并且可以更好地控制事务和提交过程。
以下是一个示例,展示了如何在Java代码中执行类似的操作:
import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class CustomerDao {
private JdbcTemplate jdbcTemplate;
// 构造函数注入
public void updateCustomerInfo() {
String sql = "SELECT * FROM customer"; // 假设customer表中有id、name等属性
List<Map<String, Object>> customers = this.jdbcTemplate.queryForList(sql);
for (Map<String, Object> customer : customers) {
Long id = Long.parseLong(customer.get("id").toString());
String name = customer.get("name").toString();
// 从中间表获取信息
String intermediateTableSql = "SELECT * FROM INTERMEDIATE_TABLE WHERE CUSTOMER_ID = ?";
List<Map<String, Object>> infoFromIntermediateTables = this.jdbcTemplate.queryForList(intermediateTableSql, new Object[]{id});
if (infoFromIntermediateTables == null || infoFromIntermediateTables.isEmpty()) {
// 如果找不到信息,则删除该客户记录
this.jdbcTemplate.update("DELETE FROM CUSTOMER WHERE ID = ?", new Object[]{id});
} else {
// 如果找到了信息,则更新客户记录
this.jdbcTemplate.update("UPDATE CUSTOMER SET NAME = ? WHERE ID = ?", new Object[]{name, id});
}
}
}
}
在这个例子中,我们首先通过一个简单的SQL查询从customer表中获取所有客户记录。然后,我们遍历这些记录,从中间表中获取与之匹配的信息。如果找到信息,我们就更新customer表中的客户记录。如果找不到信息,我们就删除该客户记录。
这种方法的好处在于我们可以更好地控制事务和提交过程,而且可以在一次查询中更新多个列。
在 SQL 层面,有一些优化可以考虑:
1、批量操作而非逐行处理:在处理大量数据时,逐行处理通常效率较低。如果可能,尝试批量操作,例如使用 IN 语句或 MULTI-TABLE UPDATE。
2、优化数据类型和索引:确保所有相关的列都使用了最优的数据类型,这可以减少存储和计算的需求。对经常用于查询的列添加索引,可以大大提高查询速度。
3、使用视图代替临时表:如果可能,尝试使用视图代替临时表。视图在创建后只计算一次,而临时表可能会在每次查询时重新计算。
4、使用连接而不是子查询:在某些情况下,连接查询可能比子查询更快。
5、尽可能减少数据库交互:尽量在一次数据库交互中完成所有需要的操作,而不是多次交互。
在 Java 代码层面,可以考虑以下优化:
1、使用批处理:如果你在 Java 中使用 JDBC 更新大量数据,使用批处理可以大大提高性能。
2、减少数据库交互:和 SQL 层面的优化一样,尽量在一次数据库交互中完成所有需要的操作。
3、预加载和缓存:预加载可能需要的对象或数据,然后在需要时从缓存中获取,而不是每次需要时都从数据库中获取。
4、使用连接池:连接池可以重用已经创建的数据库连接,避免了每次操作都要创建和关闭连接的开销。
在实施任何优化措施之前,都应先进行性能测试,以确保优化措施的效果。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。