【问题标题】:Oracle low speed in first executeOracle首次执行速度低
【发布时间】:2011-11-13 11:51:14
【问题描述】:

我在 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)

【问题讨论】:

  • explain plan怎么样?
  • 我没用过,也不知道这是干什么用的。
  • 看看吧。它将帮助您更好地了解将在服务器上运行的 hoy 查询。
  • 感谢您的建议
  • @God Lover:请不要大喊大叫。您将唤醒 DBMS 和 DBA。

标签: sql oracle


【解决方案1】:

第一次运行后执行查询只需要几毫秒的原因是Oraclecaches的结果。如果您更改 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)上运行查询,看看它是否足够快。然后我会逐渐地、一张一张地添加其余的表,看看性能开始下降的地方。

【讨论】:

  • OP 使用 Oracle 10g(据我所知)没有实现结果缓存。我错了吗?
  • 我很确定查询缓存自 8i 版起就在 Oracle 数据库中。我没有使用早期版本,但我想它已经在 8i 之前的版本中 download.oracle.com/docs/cd/A97339_01/doc/icache.100/icache_gd/…
  • 您的链接描述了 Oracle8i Cache,它是 Oracle 服务器 (download.oracle.com/docs/cd/A97339_01/doc/icache.100/icache_gd/…) 之外的中间层组件,充当缓冲区缓存(“对于此版本的 Oracle8i Cache,您必须缓存整个表;不能只缓存满足查询的部分表。因此,数据集必须是整个数据库表。"),而不是结果缓存。
  • 嗯,你是对的,我懒得去阅读谷歌实际返回的内容。但请相信我,我使用 8i 工作了 4 年,它一个查询缓存。我的工作包括很多慢查询优化,这种情况一直都在发生:第一次执行 10 秒,后续执行 50 毫秒。它是查询缓存。
  • 好的,你说的是查询计划缓存、缓冲区缓存还是结果缓存? AFAICS,你描述的效果可能是缓冲区缓存造成的……
【解决方案2】:

您很可能正在经历缓存的影响:

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

这些影响甚至可能发生在索引扫描上,但在诸如全表扫描之类的昂贵操作上尤其严重(因为涉及到大量页面)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 2019-01-05
    • 1970-01-01
    相关资源
    最近更新 更多