jdbcTemplate.query运行速度慢,有数百万条记录

时间:2017-08-15 19:49:34

标签: db2 spring-data jdbctemplate

我不知道为什么这个查询的执行速度非常慢,如果表有1.8亿的记录。我连接的数据库是DB2。

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 个答案:

答案 0 :(得分:1)

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

在评论中你回答了问题

  

为什么期望它快速运行?

使用

  

因为表格索引是在列email_localemail_domain上设置的。我在where子句中使用过的,所以期望运行得更快。

问题是,您很可能不使用这些索引。

  1. 如果它们实际上是多个索引,则数据库很可能只使用一个索引。大多数数据库大多数时间都无法组合多个索引。

  2. 如果你的where子句如下:

    where upper(email_local)=upper(:email) and upper(email_domain)=upper(:domain)
    

    这意味着您将where子句不应用于索引列,而是基于这些列来运行结果。这使得索引大多无用。

  3. 以下是您可以做的事情(可能还有更多,而不是DB2专家)

    1. add a function based index。这是你应该做的。其他更多是针对你不能做到这一点的情况(不同的RDBMS,旧版本,疯狂的数据库管理员)

    2. 将带有大写名称的列添加到表中并对其进行索引并在查询中使用它们。

    3. upper放在where子句中的列上。这显然会改变您的查询,可能无法接受。

    4. 作为最终真正的hacky方法,您可以添加使用索引的约束:

      where column between lower(:value) and upper(:value) and upper(column) = upper(:value)
      

      您需要将此方法调整为多列,并确保所有非ascii字符按预期排序(他们不会)。

    5. 在任何情况下,最好查看您的陈述explain plan并在变更之前和之后进行比较。如果你使用数亿行,你将需要这个工具。