我在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)
答案 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)
您可能正在体验缓存的影响:
即使在索引扫描中也会发生这种影响,但在全表扫描等昂贵的操作(因为触摸了大量页面)时尤其会加剧这种影响。
检查您的查询计划,看看是否有任何可能涉及大量网页的昂贵操作......