Что такое SYS_OP_UNDESCEND и SYS_OP_DESCEND в плане Oracle Explain? - PullRequest
1 голос
/ 04 августа 2020

У меня есть план Oracle объяснения, который выглядит так:

Plan hash value: 2484140766                                                                               
                                                                                                          
--------------------------------------------------------------------------------------------------------  
| Id  | Operation                      | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT               |                       |   180K|    84M|     5   (0)| 00:00:01 |  
|*  1 |  COUNT STOPKEY                 |                       |       |       |            |          |  
|   2 |   VIEW                         |                       |   180K|    84M|     5   (0)| 00:00:01 |  
|*  3 |    TABLE ACCESS BY INDEX ROWID | OSTRICH               |  6500K|   793M|     5   (0)| 00:00:01 |  
|*  4 |     INDEX RANGE SCAN DESCENDING| OSTRICH_ENDDATE_IDX_2 |     1 |       |     4   (0)| 00:00:01 |  
--------------------------------------------------------------------------------------------------------  
                                                                                                          
Predicate Information (identified by operation id):                                                       
---------------------------------------------------                                                       
                                                                                                          
   1 - filter(ROWNUM<=180000)                                                                             
   3 - filter("OSTRICH_STATUS_ID"=2)                                                                      
   4 - access(SYS_OP_DESCEND("END_DATE")>=SYS_OP_DESCEND(SYSDATE@!))                                      
       filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("END_DATE"))<=SYSDATE@!)

Я пытался понять, что происходит с этими двумя строками внизу:

4 - access(SYS_OP_DESCEND("END_DATE")>=SYS_OP_DESCEND(SYSDATE@!))                                      
       filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("END_DATE"))<=SYSDATE@!)

Что означают SYS_OP_UNDESCEND и SYS_OP_DESCEND?

Индекс, на который ссылается план объяснения (я думаю), называется убывающим индексом. (Я мало знаю об индексировании Oracle.) DDL для этого индекса:

CREATE INDEX
    OSTRICH_ENDDATE_IDX_2
ON
    OSTRICH
    (
        "END_DATE" DESC
    );

Фактический запрос выглядит следующим образом:

SELECT
 l.id,
 l.end_date,
 l.status
FROM
    (
        SELECT
            *
        from OSTRICH l2
        where END_DATE <= SYSDATE
            and OSTRICH_STATUS_ID = 2
        order by l2.END_DATE
    ) l
WHERE ROWNUM <= 180000;

Что делают SYS_OP_UNDESCEND и SYS_OP_DESCEND означают? Этот запрос занимает намного больше времени, чем я ожидал, и я пытаюсь понять, какое влияние на запрос оказывает нисходящее и неубывающее?

Ответы [ 2 ]

2 голосов
/ 04 августа 2020

Oracle реализует нисходящий индекс «как если бы» это был функциональный индекс . Индексы на основе функций вызываются, когда запрос использует вызов функции; таким образом, FBI на upper(col1) будет использоваться, когда предложение WHERE фильтрует upper(col1) = 'WHATEVER'.

. В этом случае я думаю, что SYS_OP_DESCEND - это «функция», которую Oracle использует при создании убывающего индекса. затем вызывает SYS_OP_UNDESCEND, потому что ваше предложение WHERE не подходит для убывающего индекса. Неудивительно, что производительность - отстой.

Очень мало случаев использования, когда нисходящий индекс является хорошей идеей. Почему вы используете один в этом столбце этой таблицы?

Предполагая, что для использования индекса есть веская причина, и вы не можете просто отбросить его, лучшим вариантом для повышения производительности было бы не использовать индекс для этого запроса. Выполнение чего-то подобного должно предотвратить использование оптимизатором индекса:

SELECT
 l.id,
 l.end_date,
 l.status
FROM
    (
        SELECT /*+ NO_INDEX(l2 OSTRICH_ENDDATE_IDX_2) */ 
            *
        from OSTRICH l2
        where END_DATE <= SYSDATE
            and OSTRICH_STATUS_ID = 2
        order by l2.END_DATE
    ) l
WHERE ROWNUM <= 180000;
1 голос
/ 04 августа 2020

SYS_OP_UNDESCEND и SYS_OP_DESCEND - это внутренние функции, используемые CBO, которые появляются в EXPLAIN PLAN, когда используется индекс на основе функции или была указана операция сортировки внутри предложения индекса.

В вашем В этом случае вы используете ИНДЕКС с предложением SORT

CREATE INDEX
    OSTRICH_ENDDATE_IDX_2
ON
    OSTRICH
    (
        "END_DATE" DESC
    );

В вашем плане показаны эти две операции:

  • access(SYS_OP_DESCEND("END_DATE")>=SYS_OP_DESCEND(SYSDATE@!))
  • filter(SYS_OP_UNDESCEND(SYS_OP_DESCEND("END_DATE"))<=SYSDATE@!)

Первая операция - это доступ, основанный на предложении des c index самого индекса, а вторая - фильтр. Оба появляются, потому что запрос выполняется в соответствии с природой индекса.

Я бы никогда не использовал это предложение ни в каком индексе, если только доступ не осуществляется таким образом всегда, что довольно редко, потому что сортировка разными способами - это то, что обычно SQL используется для.

Также существует эта ошибка: (исправлено в 20.1)

Ошибка 27589260 неправильный порядок сортировки из-за замены виртуального столбца в индексе на основе функции

Это снижает производительность запроса, когда в таблице присутствует виртуальный столбец и используется индекс, основанный на функциях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...