Db2 jdbcTemplate.query运行缓慢,有数百万条记录

Db2 jdbcTemplate.query运行缓慢,有数百万条记录,db2,spring-data,jdbctemplate,Db2,Spring Data,Jdbctemplate,我不知道为什么这个查询在表中有超过1.8亿条记录的情况下运行得非常慢 public CustomerEmailFreq getFreqCodeByEmail(String email, String domain) { CustomerEmailFreq customerEmailFreq = new CustomerEmailFreq(); Map namedParameters = new HashMap(); namedParameters.put("email", email); nam

我不知道为什么这个查询在表中有超过1.8亿条记录的情况下运行得非常慢

public CustomerEmailFreq getFreqCodeByEmail(String email, String domain) {
CustomerEmailFreq customerEmailFreq = new CustomerEmailFreq();
Map namedParameters = new HashMap();
namedParameters.put("email", email);
namedParameters.put("domain", domain);

String sql = "select freq_cde,email_local,email_domain,last_src_date,last_src_time from ADDRESS where upper(email_local)=upper(:email) and upper(email_domain)=upper(:domain) ORDER BY TIMESTAMP(LAST_SRC_DATE,LAST_SRC_TIME) DESC FOR READ ONLY WITH UR FETCH FIRST ROW ONLY";

this.jdbcTemplate.query(sql, namedParameters, (rs, rowNum) ->

{
    customerEmailFreq.setEmailDomain(rs.getString("EMAIL_DOMAIN").trim());
    customerEmailFreq.setEmailLocal(rs.getString("EMAIL_LOCAL").trim());
    customerEmailFreq.setFreqCode(rs.getString("FREQ_CDE"));
    customerEmailFreq.setLastSrcDate(rs.getString("LAST_SRC_DATE"));
    customerEmailFreq.setLastSrcTime(rs.getString("LAST_SRC_TIME"));
    return null;

});
return customerEmailFreq;
}


任何有助于解决这个问题的提示。

1.8亿行是一个严重的数字。因此,如果不能使用索引来限制在数据库中访问的块的数量,那么事情应该运行一段时间

在评论中回答问题


你为什么期望它跑得快


因为表索引是在
email\u local
email\u domain
列上设置的。我在where子句中使用了它,希望运行得更快

问题是,您很可能没有使用这些索引

  • 如果它们实际上是多个索引,那么数据库很可能只使用一个索引。大多数数据库在大多数情况下不能合并多个索引

  • 如果where子句如下所示:

    where upper(email_local)=upper(:email) and upper(email_domain)=upper(:domain)
    
    这意味着您将where子句应用于基于这些列的函数结果,而不是索引列。这使得索引几乎毫无用处

  • 以下是您可以做的事情(可能还有更多,这里没有DB2专家)

  • 。这才是你真正应该做的。其他的则更多地用于无法执行此操作的情况(不同的RDBMS、旧版本、mad DB admin)

  • 将名称大写的列添加到表中,并对这些列进行索引,然后在查询中使用它们

  • 在where子句中的列上删除上方的
    。这显然会改变您的查询,并且可能不会被接受

  • 作为最后一种非常有技巧的方法,您可以添加使用索引的约束:

    where column between lower(:value) and upper(:value) and upper(column) = upper(:value)
    
    您需要将这种方法适应于多列,并确保所有非ascii字符按预期进行排序(它们不会这样做)


  • 在任何情况下,查看您的陈述并在更改前后进行比较都是一个好主意。如果要处理数亿行,则需要此工具。

    直接在数据库上运行查询需要多长时间?为什么返回null?需要4分钟以上。因为我使用了lambda表达式,所以必须返回null。为什么希望它运行得快?因为表索引是在列email\u local、email\u domain.上设置的,我在where子句中使用了这些列,所以希望运行得更快。如果列email\u local上的索引,email_域不是基于表达式的索引,如果收集了适当的runstats,那么4分钟的运行时间可能是由于访问计划不佳。这是因为在两个谓词上使用函数(UPPER())。如果它是一个普通索引(或多个索引),那么DB2会因为上面的()而忽略该索引。您还需要知道所使用的隔离级别、DB2服务器操作系统平台和DB2版本,因为它们决定了基于表达式的索引是否可用。您可以从DB2获得访问计划来验证这些东西