Oracle查询:日期筛选器变得非常慢

问题描述

我有这个Oracle查询,大约需要1分钟才能得到结果:

SELECT TRUNC(sysdate - data_ricezione) AS delay
  FROM notifiche@fe_engine2fe_gateway n
 WHERE NVL(n.data_ricezione,TO_DATE('01011900','ddmmyyyy')) =
       (SELECT NVL(MAX(n2.data_ricezione),'ddmmyyyy'))
          FROM notifiche@fe_engine2fe_gateway n2
         WHERE n.id_sdi = n2.id_sdi)
--AND sysdate-data_ricezione > 15

基本上,我有一个名为“ notifiche”的表,其中的每条记录代表一种对另一种对象(发票)的更新。我想知道过去15天内哪些发票未收到任何更新。我可以通过加入notifiche n2表,获取每张发票的最新记录并评估更新日期(data_ricezione)与当前日期(sysdate)之间的差异来做到这一点。

当我添加注释条件时,查询需要花费无限时间才能完成(我的意思是小时,从没见过结局...)

这种简单条件如何使查询如此缓慢?

如何提高性能?

解决方法

尝试保持data_ricezione 单独;如果上面有索引,可能会有所帮助。

所以:从以下位置切换

and sysdate - data_ricezione > 15

and -data_ricezione > 15 - sysdate / * (-1)

and data_ricezione < sysdate - 15

通过数据库链接完成所有操作后,请查看driving_site提示是否有任何好处,即

select /*+ driving_site (n) */                --> "n" is table's alias
  trunc(sysdate-data_ricezione) as delay
from
  notifiche@fe_engine2fe_gateway n
...
,

使用解析函数来避免通过数据库链接进行自我联接。下面的查询仅从表中读取一次,将行划分为多个窗口,为每个窗口找到MAX值,然后让您根据该最大值选择行。解析功能乍看之下很棘手,但通常会导致代码更小,更高效。

select id_sdi,data_ricezion
from
(
    select id_sdi,data_ricezion,max(data_ricezion) over (partition by id_sdi) max_date
    from notifiche@fe_engine2fe_gateway
)
where sysdate - max_date > 15;

关于为什么添加简单条件会使查询变慢的原因-全部与基数估计有关。基数(行数)决定着数据库优化程序的大多数决定。联接少量数据的最佳方法可能与联接大量数据的最佳方法大不相同。 Oracle必须始终猜测一个操作返回多少行,以知道要使用哪种算法。

优化器统计信息(有关表,列和索引的元数据)是Oracle用于进行基数估计的内容。例如,要猜测由sysdate-data_ricezione > 15过滤出的行数,优化器将要知道表(DBA_TABLES.NUM_ROWS)中有多少行,该列的最大值是({{ 1}}),也许可以细分不同年龄范围内的行数(DBA_TAB_COLUMNS.HIGH_VALUE)。

所有这些信息取决于正确收集的优化器统计信息。如果DBA愚蠢地禁用了自动优化器统计信息收集,那么这些问题将一直存在。但是,即使您的系统使用了良好的设置,您使用的谓词也可能是特别困难的情况。优化器统计信息无法随意收集,因此系统仅在10%的数据更改时才收集统计信息。但是,由于您的谓词涉及DBA_TAB_HISTOGRAMS,因此即使表未更改,行的百分比也会每天更改。可能比默认计划更频繁地手动收集此表上的统计信息,或使用SYSDATE提示,或创建SQL Profile / Plan Baseline,或管理优化器统计信息和计划稳定性的多种方法之一。但是希望如果您使用分析函数而不是自联接,则不需要这些。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...