首次执行Oracle低速

时间:2011-11-13 11:51:14

标签: sql oracle

我在SQL中编写了一个从表中选择一些列的查询。我的问题是,当我在Oracle 10g中执行此查询时,大约需要7秒,但下次它会在几毫秒内执行。如果我更改了where子句,再次需要5秒以上。 如何在第一时间加快此查询?查询如下:

SELECT Id,Qflag, LetterId, LetterNo, LetterDate, InstanceDate, ViewDate, DeadlineDate 
FROM VWLETTERINSTANCESEARCH 
WHERE ( QFLAG IS NULL OR QFLAG = 0 ) AND 
  EXISTS(SELECT * FROM VWLETTERINSTANCESEARCH VW 
         where PARENTINSTANCEID=VWLETTERINSTANCESEARCH.Id AND refSenderId=1947)AND 
  EXISTS(SELECT * FROM LetterInstances ChildInstance, Folders 
         WHERE ChildInstance.ParentInstanceId=VWLETTERINSTANCESEARCH.Id AND 
               ChildInstance.FolderId=Folders.Id AND Folders.OwnerId=23) AND 
  OwnerId IN (SELECT StaffId FROM vwStaffUsers WHERE UserId=2 AND Deleted=0)

2 个答案:

答案 0 :(得分:5)

第一次运行后执行查询只需几毫秒的原因是Oracle caches结果。如果更改SQL,则Oracle会将其视为不同的查询,并且不会从缓存中提供结果,而是执行新查询。

如何加快首次执行是一个难题。您需要发布explain plan,如果您想获得帮助,可能还需要回答其他问题。

我的第一次尝试是消除子查询,尽管Oracle最近很好地优化了这一点:

SELECT DISTINCT VW1.Id, VW1.Qflag, VW1.LetterId, VW1.LetterNo, VW1.LetterDate, 
  VW1.InstanceDate, VW1.ViewDate, VW1.DeadlineDate 
FROM 
  VWLETTERINSTANCESEARCH VW1,
  VWLETTERINSTANCESEARCH VW2,
  LetterInstances, ChildInstance, Folders, 
  vwStaffUsers SU
WHERE ( QFLAG IS NULL OR QFLAG = 0 ) 
  AND (VW1.PARENTINSTANCEID=VW2.Id AND VW2.refSenderId=1947)
  AND (ChildInstance.ParentInstanceId=VW1.Id AND 
               ChildInstance.FolderId=Folders.Id AND Folders.OwnerId=23) 
  AND (VW1.OwnerId = SU.StaffId AND SU.UserId=2 AND SU.Deleted=0)

修改 此外,我尝试仅在主表(即VWLETTERINSTANCESEARCH VW1)上运行查询,并查看它是否足够快。然后我逐渐逐步添加其余表,并查看性能开始降低的位置。

答案 1 :(得分:2)

您可能正在体验缓存的影响:

  • 第一次执行查询时,Oracle缓存仍然是“冷”。在查询执行时,Oracle会缓存查询执行期间触及的页面。
  • 当您重新执行查询时,所需的页面已经在缓存中,所以速度要快得多。
  • 当您更改WHERE时,查询会触摸不同的页面,并且循环会再次重复。

即使在索引扫描中也会发生这种影响,但在全表扫描等昂贵的操作(因为触摸了大量页面)时尤其会加剧这种影响。

检查您的查询计划,看看是否有任何可能涉及大量网页的昂贵操作......