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

z6psavjg  于 2023-03-12  发布在  DB2
关注(0)|答案(1)|浏览(289)

我不知道为什么这个查询运行非常缓慢,如果表有更多的记录180百万。数据库我连接的是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;

}
有什么线索能帮上忙吗。

xdnvmnnf

xdnvmnnf1#

1.8亿行是一个很大的数字,所以如果他们不能使用索引来限制数据库中访问的块的数量,那么事情应该会运行一段时间。
在评论中回答问题
你为什么期望它跑得快?

因为表索引是在列email_localemail_domain上设置的。我在where子句中使用了它,所以希望运行得更快。
问题是,您很可能没有使用这些索引。
1.如果它们实际上是多个索引,那么数据库很可能只使用一个索引,大多数数据库在大多数情况下不能合并多个索引。
1.如果where子句如下所示:

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

这意味着where子句不是应用于索引列,而是应用于基于这些列的函数结果,这使得索引几乎毫无用处。
下面是您可以做的事情(可能还有更多,这里不是DB2Maven)

  1. add a function based index。这是你应该做的一个。其他的更多的情况下,你不能做这个(不同的RDBMS,旧版本,疯狂的DB管理)
    1.向表中添加名称为大写的列,对这些列进行索引,并在查询中使用它们。
    1.删除where子句中列上的upper,这显然会改变您的查询,并且可能是不可接受的。
    1.作为最后一个非常笨拙的方法,您可以添加使用索引的约束:
where column between lower(:value) and upper(:value) and upper(column) = upper(:value)

您需要将这种方法应用于多列,并确保任何非ascii字符都按预期排序(实际上它们不会)。
在任何情况下,查看语句explain plan并比较更改前后的语句都是一个好主意,如果要处理数亿行,则需要使用此工具。

相关问题