oracle - 相同的查询,但在11g和12c中有不同的计划

时间:2016-01-06 00:34:53

标签: oracle optimization oracle11g pagination oracle12c

此问题与this question有关。 这是我尝试在12c中使用的代码

  SELECT * FROM DMProgDate_00001
  WHERE 1=1
  AND ProgressOID IN ( 
    SELECT P.OID FROM (
      SELECT OID FROM (
        SELECT A.OID, ROWNUM as seqNum FROM (
          SELECT OID FROM DMProgress_00001 
            WHERE 1=1
            AND Project = 'Moho'
            AND Phase = 'Procurement'
            AND Displine = 'Q340'
            ORDER BY actCode
          ) A
          WHERE ROWNUM <= 20
      ) WHERE seqNum > 0
    ) P
  );
  • 结果

    11g:1秒内

    12c:超过8秒

这是11g中的查询计划 enter image description here

这是12c中的查询计划 enter image description here

当我取出所有分页代码(如下所示)时。 12c中的查询足够快,因为11g BUT需要分页查询。

  SELECT  * FROM DMProgDate_00001
  WHERE 1=1
  AND ProgressOID IN ( 
    SELECT P.OID FROM (
          SELECT OID FROM DMProgress_00001 
            WHERE 1=1
            AND Project = 'Moho'
            AND Phase = 'Procurement'
            AND Displine = 'Q340'
            ORDER BY actCode
    ) P
  );

这是12c中的查询(没有分页)计划 enter image description here

我尝试了OFFSET ..关键字(仅支持12c)和optimizer_features_enable(&#39; 11.2.0.4&#39;),但结果与上述相同(超过8秒)。

我们需要同时支持11g和12c,我知道绕道来解决这个问题(在my pre-question中)但是我不想将它保持为相同的查询代码。有没有可以解决这个问题的选项或设置?

将查询计划添加为文本 (它们是不同的表名,但是表结构和内容相同)

12c - over 3 sec
Plan hash value: 3742986389

-----------------------------------------------------------------------------------------
| Id  | Operation            | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                  |     1 |   153 |   204   (0)| 00:00:01 |
|*  1 |  FILTER              |                  |       |       |            |          |
|   2 |   TABLE ACCESS FULL  | DMPROGDATE_00001 |     1 |   153 |   102   (0)| 00:00:01 |
|*  3 |   FILTER             |                  |       |       |            |          |
|*  4 |    COUNT STOPKEY     |                  |       |       |            |          |
|*  5 |     TABLE ACCESS FULL| DMPROGRESS_00001 |    26 |  2288 |   102   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( EXISTS (<not feasible>)
   3 - filter("OID"=:B1)
   4 - filter(ROWNUM<=20)
   5 - filter("PROJECT"='Moho' AND "PHASE"='Procurement' AND "DISPLINE"='Q340')

Note
   - dynamic statistics used: dynamic sampling (level=2)
   - 1 Sql Plan Directive used for this statement





11g - 0.01 sec

Plan hash value: 833434956
-----------------------------------------------------------------------------------------
| Id  | Operation            | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                  |    13 |  1157 |    57   (2)| 00:00:01 |
|*  1 |  HASH JOIN RIGHT SEMI|                  |    13 |  1157 |    57   (2)| 00:00:01 |
|   2 |   VIEW               | VW_NSO_1         |     3 |    81 |    34   (0)| 00:00:01 |
|*  3 |    COUNT STOPKEY     |                  |       |       |            |          |
|*  4 |     TABLE ACCESS FULL| DMPROGRESS_00037 |     3 |    99 |    34   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL  | DMPROGDATE_00037 |  7388 |   447K|    22   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("PROGRESSOID"="OID")
   3 - filter(ROWNUM<=20)
   4 - filter("DISPLINE"='Q340' AND "PHASE"='Procurement' AND "PROJECT"='Moho')

1 个答案:

答案 0 :(得分:0)

即使在相同版本的两个环境之间,选择的优化器选择的执行计划也会有很大差异,而不仅仅是11g和12c。这取决于很多因素,但主要是:

  • 表格中的行数(它们在envs之间是否相似?)
  • 存在哪些索引(两个dbs是否具有完全相同的索引?)
  • 是否有表格和索引的统计信息,以及它们是如何更新的?如果不是最新的,请收集表表的统计信息。

如果您可以发布这些详细信息,我可以提供更有用的答案。

此外,代码看起来像自动生成,如果您可以自由修改它们,根据细节,我们可以建议重写的查询和/或提示。

如果无法修改代码,则可以强制执行带有SQL计划管理(SPM)的计划 - 从运行速度更快的数据库导出并导入到其他数据库中。

更新

使用此简化版本的SQL生成计划:

SELECT * FROM DMProgDate_00001
 WHERE ProgressOID IN ( 
   SELECT OID FROM DMProgress_00001 
    WHERE Project = 'Moho'
      AND Phase = 'Procurement'
      AND Displine = 'Q340'
      AND ROWNUM <= 20
    ORDER BY actCode
  );