【发布时间】:2017-12-24 22:05:30
【问题描述】:
鉴于:
带有事件的视图
DataView。事件与时间戳Inst和数据列一起存储。事件分为特定的班次或间隔,从每天 06:00、14:00 和 20:00 开始。
View
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 秒内运行。对于给定的应用程序来说足够快。
问题:
为什么第一个解决方案比第二个解决方案慢?我猜想子查询是针对
DataView的每一行执行的,但希望优化器能解决这个问题。是否有更高效/更好的方法来执行第一个查询?使用
CurrShift.StartTime比在应用程序中计算时间戳更方便。
@Robbie Toyota:是的,Inst 和 StartTime 在两个表中都绝对属于 date 类型。
@dnoeth: 1.) 子查询只返回一行。该表仅包含当前班次的开始和结束时间戳及其名称。 2.) 无论如何我尝试了 MAX(..),但没有成功。
解释计划 我按照 Robbie 的建议执行了解释计划,并看到计划中的巨大差异。但我不知道如何处理这些信息:
慢查询:
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 占用。
【问题讨论】:
-
InstFROM 是时间戳吗?我不在 Oracle 中工作(我从 sql 标记来到这里),但如果 InstFROM 与 Inst 的数据类型不同,则 Inst 上的索引可能不会被使用。
-
标量子查询应该返回一行(否则无论如何都会失败),您可能需要 top apply MAX:
WHERE Inst >= (SELECT MAX(Inst) FROM Time_Table)。但我怀疑这是你真正想要/需要的。 -
好吧,你知道
Time_Table中只有一行,优化器没有(除非它是DUAL)。试试 MAX。 -
你用
EXPLAIN PLAN检查查询计划了吗? -
发布解释计划的内脏 sn-ps 是毫无意义的练习。它们没有告诉我们任何信息,因此我们无法使用它们来解释为什么您的两个查询具有如此不同的执行配置文件。性能调优只关注细节。如果您无法发布我们需要的详细信息(出于公司机密原因或其他原因),您应该删除此问题。
标签: sql oracle performance oracle10g query-optimization