2017-07-19 61 views
-1

考虑:子查询减缓我的查询下

  • 的视角DataView的事件。事件存储在时间戳Inst和数据列中。

  • 事件发生在每天06:00,14:00和20:00的特定轮班或间隔。

  • 该视图DataView每个班次持有数百个事件,并有几年积压。

  • 当前班次的开始时间戳存储在表CurrShift中。该列与该信息标记为StartTime该表只包含具有该信息的一行。

目标:

检索所有事件从目前的转变,即其中DataView.Inst >= CurrShift.StartTime

解决方案,但是进展缓慢:

SELECT * 
FROM DataTable 
WHERE Inst >= (SELECT StartTime FROM CurrShift); 

查询运行时间超过30分钟。对于给定的应用程序这是不可接受的。 ,但仅限于固定日期

更快的查询

SELECT * 
FROM Data_Table 
WHERE Inst >= TO_DATE('19.07.2017 14:00:00'); 

该查询运行在下2.0秒。对于给定的应用程序足够快。

问:

  1. 为什么是缓慢相比,第二个第一个解决方案?我猜这个子查询是针对DataView的每一行执行的,但是希望优化器能够解决这个问题。

  2. 是否有更高性能/更好的方法来做第一个查询?使用CurrShift.StartTime比计算应用程序中的时间戳更方便。

@Robbie丰田:是,InstStartTime绝对date类型既是表所示。

@dnoeth: 1.)子查询只返回一行。该表仅包含当前班次的开始和结束时间戳及其指定。 2.)无论如何,我尝试了MAX(..),但没有成功。

解释计划 我执行解释计划,如罗比建议,并看到计划的巨大差异。但我不知道做什么用的信息做:

慢查询:

SELECTED STATEMENT 
    HASH JOIN RIGHT OUTER 
    TABLE ACCESS FULL 
    HASH JOIN RIGHT OUTER 
     TABLE ACCESS FULL 
     HASH JOIN RIGHT OUTER 
     TABLE ACCESS FULL 
    ... 

快速查询:

SELECTED STATEMENT 
    NESTED LOOPS OUTER 
    NESTED LOOPS OUTER 
     NESTED LOOPS OUTER 
... 

完全不同的引用的表,和巨大的CPU海岸用于哈希。

+1

InstFROM是一个时间戳吗?我不在Oracle工作(我是从sql标记来的),但是如果InstFROM与Inst不同,那么Inst上的索引可能不会被使用。 – RToyo

+0

标量子查询应返回一行(否则它将失败),您可能需要顶部应用MAX:WHERE Inst> =(SELECT MAX(Inst)FROM Time_Table)。但我怀疑这是你的行为想要/需要的。 – dnoeth

+1

那么,你知道'Time_Table'中只有一行,优化器没有(除非它是'DUAL')。试试MAX。 – dnoeth

回答

0

尝试避免与下面的子查询:

DECLARE t Time_Table.Inst%TYPE; 
SELECT Inst INTO t FROM Time_Table; 
SELECT * FROM Data_Table WHERE Inst >= t; 
+0

这不是Oracle语法。这个问题被标记为'[oracle]',所以答案需要提出Oracle语法。请注意,'[sql]'只是泛型SQL查询;有关MS SQL Server的问题被标记为'[sql-server]' – APC

+0

已更新。我的错。 – 2017-07-20 17:47:51

0

这解决了问题,2),但它是一个有点凌乱的办法。 来自原始Fast Solution的TO_DATE()可以用SYSDATE替代,而不会有任何明显的性能损失。

回顾:

  • 的WHERE与SYSDATE子句运行速度相当快

  • 这是很难计算的转变的开始时间戳出SYSDATE

  • 有提供开始时间戳的表格

  • A WHERE使用子查询到该表子句是缓慢

解决方案:

  • 用WHERE子句SYSDATE减少原始数据到当天

  • 过滤子集WHERE子句和子查询放入开始时间戳表中的速度很快,因为它只是原始数据的一小部分

代码:

SELECT * 
FROM (
    SELECT * 
    FROM Data_Table 
    WHERE Inst >= SYSDATE - 1; 
) 
WHERE Inst >= (SELECT StartTime FROM CurrShift); 

执行时间大致是从问题的快速解法 1.5。

关于问题1:

我仍然不知道为什么子查询的速度如此之慢。但我学会了更好地解释解释计划。这个观点如此复杂和深刻地嵌套,以至于从那里的解释计划开始很困难。有趣的事实:解释计划预计查询运行9小时。