【问题标题】:PL/SQL Developer runs queries faster when contains commentsPL/SQL Developer 在包含注释时运行查询更快
【发布时间】:2014-09-15 00:59:00
【问题描述】:

我正在尝试提高针对 Oracle 10g 数据库的 SQL 查询的性能。我有以下两个查询:

查询 1

SELECT DISTINCT 
    WMS_EVENT_LOG.LOG_ID,
    WMS_EVENT_LOG.EVENT_ARG4,
    WMS_EVENT_LOG.EVENT_TYPE,
    WMS_EVENT_LOG.EVENT_ARG1,
    WMS_EVENT_LOG.EVENT_ARG3,
    WMS_EVENT_LOG.PROD_ITEM_ID,
    TRUNC(WMS_EVENT_LOG.LOG_DATE) AS LOG_DATE,
    WMS_EVENT_LOG.PALLET_ID,
    WMS_EVENT_LOG.LOG_USER,
    WMS_EVENT_LOG.POSTED_TO_KCAT,
    POSTEDWMSTRANS.POSTTRAN,
    DECODE(POSTEDWMSTRANS.POSTTRAN, 'Y', POSTEDWMSTRANS.CMNT, WMS_EVENT_LOG.EVENT_ARG3) AS CMNT --cmnt = comment
FROM 
    VMR_WMSEVENTLOG WMS_EVENT_LOG, 
    VM_ADJUST_REASON ADJUST_REASON,
    ( 
      SELECT 
          INVENTORY.BOM_TYPE AS POSTTRAN,
          INVENTORY.PROD_ITEM_ID,
          INVENTORY.CMNT,
          INVENTORY.WMSLINK
      FROM 
          VR_BOM INVENTORY
      WHERE 
          INVENTORY.BOM_TDATE >= TO_DATE(:report_start_date, 'YYYY/MM/DD') - 15 AND 
          INVENTORY.BOM_TDATE < TO_DATE(:report_end_date, 'YYYY/MM/DD') + 15 AND
          INVENTORY.WMSLINK IS NOT NULL AND 
          INVENTORY.BOM_TYPE <> 'HLD' 
    ) POSTEDWMSTRANS
WHERE 
    WMS_EVENT_LOG.LOG_DATE >= TO_DATE(:report_start_date, 'YYYY/MM/DD') AND 
    WMS_EVENT_LOG.LOG_DATE < TO_DATE(:report_end_date, 'YYYY/MM/DD') AND 
    WMS_EVENT_LOG.EVENT_TYPE = 31 AND
    ADJUST_REASON.ADJUST_REASON_CODE NOT IN ('SPL') AND
    ADJUST_REASON.ADJUST_REASON_CODE = WMS_EVENT_LOG.EVENT_ARG1 AND ( 
        WMS_EVENT_LOG.EVENT_ARG1 <> 'MOV' AND 
        WMS_EVENT_LOG.EVENT_ARG2 = 'ADJUST' 
    ) AND 
    WMS_EVENT_LOG.PROD_ITEM_ID = POSTEDWMSTRANS.PROD_ITEM_ID(+) AND
    WMS_EVENT_LOG.EVENT_ARG4 = POSTEDWMSTRANS.WMSLINK(+)  

查询 2

--VARIABLE report_start_date VARCHAR
--VARIABLE report_end_date VARCHAR

SELECT DISTINCT 
    WMS_EVENT_LOG.LOG_ID,
    WMS_EVENT_LOG.EVENT_ARG4,
    WMS_EVENT_LOG.EVENT_TYPE,
    WMS_EVENT_LOG.EVENT_ARG1,
    WMS_EVENT_LOG.EVENT_ARG3,
    WMS_EVENT_LOG.PROD_ITEM_ID,
    TRUNC(WMS_EVENT_LOG.LOG_DATE) AS LOG_DATE,
    WMS_EVENT_LOG.PALLET_ID,
    WMS_EVENT_LOG.LOG_USER,
    WMS_EVENT_LOG.POSTED_TO_KCAT,
    POSTEDWMSTRANS.POSTTRAN,
    DECODE(POSTEDWMSTRANS.POSTTRAN, 'Y', POSTEDWMSTRANS.CMNT, WMS_EVENT_LOG.EVENT_ARG3) AS CMNT --cmnt = comment
FROM 
    VMR_WMSEVENTLOG WMS_EVENT_LOG, 
    VM_ADJUST_REASON ADJUST_REASON,
    ( 
      SELECT 
          INVENTORY.BOM_TYPE AS POSTTRAN,
          INVENTORY.PROD_ITEM_ID,
          INVENTORY.CMNT,
          INVENTORY.WMSLINK
      FROM 
          VR_BOM INVENTORY
      WHERE 
          INVENTORY.BOM_TDATE >= TO_DATE(:report_start_date, 'YYYY/MM/DD') - 15 AND 
          INVENTORY.BOM_TDATE < TO_DATE(:report_end_date, 'YYYY/MM/DD') + 15 AND
          INVENTORY.WMSLINK IS NOT NULL AND 
          INVENTORY.BOM_TYPE <> 'HLD' 
    ) POSTEDWMSTRANS
WHERE 
    WMS_EVENT_LOG.LOG_DATE >= TO_DATE(:report_start_date, 'YYYY/MM/DD') AND 
    WMS_EVENT_LOG.LOG_DATE < TO_DATE(:report_end_date, 'YYYY/MM/DD') AND 
    WMS_EVENT_LOG.EVENT_TYPE = 31 AND
    ADJUST_REASON.ADJUST_REASON_CODE NOT IN ('SPL') AND
    ADJUST_REASON.ADJUST_REASON_CODE = WMS_EVENT_LOG.EVENT_ARG1 AND ( 
        WMS_EVENT_LOG.EVENT_ARG1 <> 'MOV' AND 
        WMS_EVENT_LOG.EVENT_ARG2 = 'ADJUST' 
    ) AND 
    WMS_EVENT_LOG.PROD_ITEM_ID = POSTEDWMSTRANS.PROD_ITEM_ID(+) AND
    WMS_EVENT_LOG.EVENT_ARG4 = POSTEDWMSTRANS.WMSLINK(+)

如您所见,两个查询之间的唯一区别是顶部的 cmets。

由于某种原因,当我在 PL/SQL 开发人员中多次运行 query 2 时,它在一秒钟内完成。当我在同一环境中多次运行query 1 时,需要 15 秒才能完成。

我检查了返回的行,它们都返回了相同数量的具有相同数据的行。

为什么查询 2 会更快完成?
我相信这可能是 PL/SQL Developer 中的一个设置给了我错误的信息。

注意
所有这些最初都是为 8i 编写的,我正在为 10g 改进它。

【问题讨论】:

  • 关闭 pl/sql dev,关闭你的数据库,重新启动,启动 plsqldev,运行一次查询 2 并测量执行需要多长时间
  • @Sebas 这是我试图加快速度的遗留代码,非常感谢您的建议。
  • 猜猜重启数据库后会发生什么。如果问题消失了,你将永远不知道如何真正解决它,直到它再次发生并且你有机会。在 Oracle 工作的 20 年中,我几乎从来没有在稳定修补过的系统上重新启动 Oracle(注意我说的是虚拟的......是的,有一些案例)。您应该能够使用管理命令完成您需要的任何事情。那么重启有什么作用呢?刷新 SGA 和所有缓存并强制一切冷启动。在一切升温之前,您将失去“真实世界”的调优环境。
  • 好吧,然后假设更快的时间是由于缓存。现在是时候优化您的查询了:)
  • 如果您想进行优化,可以通过导航到 $ORACLE_HOME/rdbms/admin 目录来获取适合您的 oracle 数据库的 plan_table ddl 脚本。

标签: sql oracle plsqldeveloper sql-tuning


【解决方案1】:

第一个查询在共享池中(对应于 cmets 中引用的现有遗留过程)。第一个查询使用来自共享池的编译计划,因此刷新时间更短,尽管两个查询具有相同的解释计划(为什么它们会有不同的解释计划)。

【讨论】:

  • @Sebas,codenheim 这是一个非常协作的答案。
  • 缓冲区缓存比共享池更有可能。解析单个查询的额外时间很少引起注意,除非发生了一些奇怪的事情,例如大型动态采样。缓冲区缓存可以很容易地解释超过几秒钟的差异。尽管这个问题中的某些内容似乎仍然是错误的。如果这两个查询都运行了多次,那么缓冲区缓存或共享池都不重要。
猜你喜欢
  • 2014-05-31
  • 1970-01-01
  • 2011-06-04
  • 2011-04-29
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多