我使用toad for Oracle运行一个运行时间太长的查询,有时超过15分钟。
该查询正在提取备忘录,这些备忘录将由经理批准。查询没有带回很多行。通常,当它运行时,它将返回大约30或40行。查询需要访问几个表以获取其信息,因此我使用了很多连接来获取此信息。
我在下面附上了我的查询。 如果有人可以帮助优化这个查询,我会非常非常好。
查询:
SELECT (e.error_Description || DECODE(t.trans_Comment, 'N', '', '','', ' - ' || t.trans_Comment)) AS Title,
t.Date_Time_Recorded AS Date_Recorded,
DECODE(t.user_ID,0,'System',(SELECT Full_Name FROM employee WHERE t.user_Id = user_id)) AS Recorded_by,
DECODE(t.user_ID,0, Dm_General.getCalendarShiftName(t.Date_Time_Recorded), (SELECT shift FROM employee WHERE t.user_Id = user_id)) AS Shift,
l.Lot_Number AS entity_number,
ms.Line_Num,
'L' AS Entity_Type,
t.entity_id, l.lot_Id AS Lot_Id
FROM DAT_TRANSACTION t
JOIN ADM_ERRORCODES e ON e.error_id = t.error_id
JOIN ADM_ACTIONS a ON a.action_id = t.action_id,
DAT_LOT l
INNER JOIN Status s ON l.Lot_Status_ID = s.Status_ID,
DAT_MASTER ms
INNER JOIN ADM_LINE LN ON ms.Line_Num = LN.Line_Num
WHERE
(e.memo_req = 'Y' OR a.memo_req = 'Y')
AND ms.Run_type_Id = Constants.Runtype_Production_Run --Production Run type
AND s.completed_type NOT IN ('D', 'C', 'R') -- Destroyed /closed / Released
AND LN.GEN = '2GT'
AND (NOT EXISTS (SELECT 1 FROM LNK_MEMO_TRANS lnk, DAT_MEMO m
WHERE lnk.Trans_ID = t.trans_id AND lnk.Memo_ID = m.Memo_ID
AND NVL(m.approve, 'Y') = 'Y'))--If it's null, it's
been created and is awaiting approval
AND l.Master_ID = ms.Master_ID
AND t.Entity_ID = l.Lot_ID
AND t.Entity_Type IN ('L', 'G');
答案 0 :(得分:5)
查询性能不佳的常见原因是Oracle无法找到合适的索引。将EXPLAIN PLAN
与TOAD一起使用,以便Oracle可以告诉您它认为执行查询的最佳方式。这应该会让你知道何时使用索引,何时不使用。
有关一般指示,请参阅http://www.orafaq.com/wiki/Oracle_database_Performance_Tuning_FAQ
请参阅here了解EXPLAIN PLAN。
答案 1 :(得分:3)
您的SQL中有一些函数调用:
SQL中的函数调用很慢,并且根据查询计划可能多次被冗余调用 - 例如计算最终被过滤掉的行的dm_general.getcalendarshiftname。
要查看这是否是一个重要因素,请尝试暂时用文字常量替换函数调用,看看性能是否有所改善。
有时可以通过重构查询来减少函数调用的次数:
select /*+ no_merge(v) */ a, b, c, myfunction(d)
from
( select a, b, c, d
from my_table
where ...
) v;
这可确保仅对结果中出现的行调用myfunction。
答案 2 :(得分:0)
我已经用文字常量替换了函数调用,这只会加速一秒或2秒。查询仍然需要大约50秒才能运行。
我可以在连接周围做些什么来帮助实现这一目标。在这里正确使用了INNER JOIN功能。
我不确定我明白你对下面的意思或如何使用它。 当我尝试在第二个选择中调用该函数时,我得到错误d无效的标识符 select / * + no_merge(v)* / a,b,c,myfunction(d) 从 (选择a,b,c,d 来自my_table 哪里...... )v;
非常感谢任何其他观点
答案 3 :(得分:0)
在我们说任何明智的事情之前,我们必须先看看时间花在哪里。这意味着你必须先收集一些信息。
因此,我对这样一个问题的标准反应是:http://forums.oracle.com/forums/thread.jspa?threadID=501834
此致 罗布。