为什么Oracle查询在Java中很慢,但在sqlDeveloper中直接执行时却要快得多?

yshpjwxd  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(143)

我在db表中有大约100k条记录,当我在oracle sqlDeveloper中执行此查询时,获取100k条记录需要大约33秒。

  1. select wflworkflo1_.REF_ID from ( select REF_ID, START_DATE from OS_HISTORYSTEP WHERE START_DATE < to_date('20/09/2023' , 'dd/mm/yyyy') UNION ALL select REF_ID, START_DATE from OS_CURRENTSTEP WHERE START_DATE < to_date('20/09/2023' , 'dd/mm/yyyy')) wflworkflo1_ WHERE REF_ID NOT IN (SELECT DISTINCT REF_ID FROM (select REF_ID, START_DATE from OS_HISTORYSTEP WHERE START_DATE >= to_date('20/09/2023' , 'dd/mm/yyyy') UNION ALL select REF_ID, START_DATE from OS_CURRENTSTEP WHERE START_DATE >= to_date('20/09/2023' , 'dd/mm/yyyy')) INT_WFL GROUP BY REF_ID) group by wflworkflo1_.REF_ID having max(wflworkflo1_.START_DATE) < to_date('20/09/2023' , 'dd/mm/yyyy');

在我的java程序中,这是运行查询的方法。

  1. public List<String> findCurrHistStepRefIdWithStartDate(String targetStartDate)
  2. throws BocException {
  3. StringBuffer sql = new StringBuffer();
  4. sql.append(
  5. "select wflworkflo1_.REF_ID from ( select REF_ID, START_DATE from OS_HISTORYSTEP WHERE START_DATE < to_date(?, 'dd/mm/yyyy') UNION ALL select REF_ID, START_DATE from OS_CURRENTSTEP WHERE START_DATE < to_date(?, 'dd/mm/yyyy')) wflworkflo1_ WHERE REF_ID NOT IN (SELECT DISTINCT REF_ID FROM (select REF_ID, START_DATE from OS_HISTORYSTEP WHERE START_DATE >= to_date(?, 'dd/mm/yyyy') UNION ALL select REF_ID, START_DATE from OS_CURRENTSTEP WHERE START_DATE >= to_date(?, 'dd/mm/yyyy')) INT_WFL GROUP BY REF_ID) group by wflworkflo1_.REF_ID having max(wflworkflo1_.START_DATE) < to_date(?, 'dd/mm/yyyy')");
  6. JdbcTemplate template = getJdbcTemplate();
  7. return template.queryForList(sql.toString(), String.class,
  8. targetStartDate, targetStartDate, targetStartDate, targetStartDate,
  9. targetStartDate);
  10. }

这个Java函数需要1个多小时才能返回结果。为什么会有这么大的差别呢?

ryhaxcpt

ryhaxcpt1#

重写与分析函数的连接应该可以避免大多数潜在的数据库问题。由于重写的查询没有连接,所以执行计划出错的可能性很小。作为一个额外的好处,新的代码更小,可以说更简单。

  1. -- ref_ids that only have old data.
  2. select distinct ref_id
  3. from
  4. (
  5. --all data along with counts of new dates per ref_id.
  6. select ref_id, start_date,
  7. sum(case when start_date >= to_date('20/09/2023' , 'dd/mm/yyyy') then 1 else 0 end)
  8. over (partition by ref_id) new_dates_per_ref_id
  9. from
  10. (
  11. --all data
  12. select ref_id, start_date from os_historystep
  13. union all
  14. select ref_id, start_date from os_currentstep
  15. )
  16. )
  17. where start_date < to_date('20/09/2023' , 'dd/mm/yyyy')
  18. and new_dates_per_ref_id = 0;

然而,这个答案仅仅是一个解决方案。您可能需要深入研究执行计划并找出为什么会发生此问题。为此,我建议您遵循astentx的建议并使用dbms_sql_monitor.report_sql_monitor。但是解决困难的Oracle性能问题可能需要很长时间,所以如果您没有时间花在查询调优上,那么避免这个问题也没有什么错。

展开查看全部

相关问题