oracle — тот же запрос, но другой план в 11g и 12c

Этот вопрос относится к этому вопросу. Это код, который я пытаюсь использовать в 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 секунды

    12с: более 8 секунд

Это план запроса в 11g введите здесь описание изображения

Это план запроса в 12c введите здесь описание изображения

Когда я вынимаю весь код разбиения на страницы (как показано ниже). запрос в 12c достаточно быстр, как 11g, НО нужен запрос на разбиение на страницы.

  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 введите здесь описание изображения

Я попробовал OFFSET.. ключевое слово (поддержка только 12c) и optimizer_features_enable('11.2.0.4'), но результат тот же, что и выше (более 8 секунд).

Нам нужно поддерживать как 11g, так и 12c, и я знаю обходной путь, чтобы решить эту проблему (в мой предварительный вопрос), НО я не хочу оставлять его как тот же код запроса. Есть ли какая-либо опция или настройка, которая может решить этот вопрос?


добавлен план запроса в виде текста (они имеют другое имя таблицы, но имеют одинаковую структуру и содержимое таблицы)

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')

person DK2    schedule 06.01.2016    source источник
comment
Создается ли SQL визуальным инструментом? У вас есть возможность переопределить SQL? (Причина, по которой я спрашиваю, заключается в том, что есть более эффективные способы написать это).   -  person Vampiro    schedule 06.01.2016
comment
Я использую Oracle SQL Delvoper, и он поддерживает изменение соединения с базой данных, выбрав список.   -  person DK2    schedule 06.01.2016
comment
Запустите EXPLAIN PLAN FOR your_sql_query, а затем SELECT * FROM TABLE( DBMS_XPLAN.DISPLAY ) на 11.2g и 12c, а затем скопируйте и вставьте их результат как обычный текст, а не как растровые изображения. Растровые изображения очень трудно читать. Спасибо.   -  person krokodilko    schedule 06.01.2016
comment
... FROM (SELECT ..., ROWNUM as seqNum FROM ...) WHERE seqNum > 0 Я не уверен, чего вы пытаетесь достичь, seqNum всегда будет больше нуля.   -  person Shannon Severance    schedule 06.01.2016
comment
Это динамический запрос, сделанный ibatis, поэтому числа (0, 20) можно изменить, например (20, 40) и т. д.   -  person DK2    schedule 06.01.2016


Ответы (1)


План выполнения, выбранный выбранным оптимизатором, может сильно различаться даже между двумя средами одной и той же версии, а не только 11g и 12c. Это зависит от многих факторов, но в основном:

  • Количество строк в таблице (одинаковы ли они между envs?)
  • Какие индексы присутствуют (у обеих баз данных одинаковые индексы?)
  • Имеются ли статистические данные для таблицы и индексов и насколько они актуальны? Если она не актуальна, соберите статистику для таблиц и индексов.

Если вы можете опубликовать эти данные, я могу дать более полезный ответ.

Кроме того, код выглядит автоматически сгенерированным, если вы можете изменить его, основываясь на деталях, мы можем предложить переписанный запрос и / или подсказки.

Если вы не можете изменить код, вы можете форсировать план с помощью SQL Plan Management (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
  );
person Vampiro    schedule 06.01.2016
comment
Я могу сказать, что 1. это одинаковое количество строк в таблице. 2. обе таблицы имеют одинаковые индексы. 3. Не делайте это «актуальным». они были сделаны в разное время (сделано 3 месяца назад за 11 г, сделано 2 дня назад за 12 центов). Вы хотите увидеть информацию о таблице V$INSTANCE? - person DK2; 06.01.2016
comment
В SQLDeveloper щелкните правой кнопкой мыши таблицу и выберите «Собрать статистику». Если у вас нет привилегий, попросите администратора баз данных сделать это. Затем снова запустите запрос, зафиксировав план, как упоминал @kordirko. - person Vampiro; 06.01.2016