2011-11-13 59 views
1

我在SQL中编写了一个查询,用于从表中选择一些列。我的问题是,当我在Oracle 10g中执行此查询时,大约需要7秒,但下次执行时在几个毫秒内。如果我改变where子句,则需要5秒以上。 ? 我怎么能在第一时间加速这个查询的查询是这样的:Oracle低速首次执行

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) 
+1

如何使用'explain plan'? –

+0

我没有使用它,我不知道这是什么。 – Amin

+0

看看它。它会帮助你理解更好的Hoy查询将在服务器上运行。 –

回答

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 ),看看它是否足够快。然后,我会逐渐添加其余表格,并逐一查看表现开始下降的位置。

+0

OP使用Oracle 10g(据我所知)没有实现结果缓存。我错了吗? –

+0

我非常肯定查询缓存是自版本8i以来的Oracle数据库。我没有使用早期版本,但我想它已经在8i之前的版本中http://download.oracle.com/docs/cd/A97339_01/doc/icache.100/icache_gd/ic_manag.htm – bpgergo

+0

您的链接描述了Oracle8i缓存,Oracle服务器之外的中间层组件(http://download.oracle.com/docs/cd/A97339_01/doc/icache.100/icache_gd/ic_intro.htm#1001429),充当缓冲区缓存(* “对于此版本的Oracle8i Cache,必须缓存整个表;不能缓存满足查询的表的部分,因此,数据集必须是整个数据库表。”*),而不是**结果**缓存。 –

2

很可能遇到缓存的效果:

  • 第一次执行查询,Oracle缓存仍然“冷”。在查询执行时,Oracle缓存在查询执行期间被触摸的页面。
  • 当您重新执行查询时,所需页面已存在于缓存中,因此速度更快。
  • 当你改变WHERE时,查询接触不同的页面,循环再次重复。

这些种效果可以在索引扫描,即使发生,但昂贵的操作,特别是加剧了诸如全表扫描(因为有大量的网页感动)。

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