Выражение Oracle EBS в индексированном столбце предотвращает использование индекса - PullRequest
0 голосов
/ 26 апреля 2018

База данных Oracle 11.1.0.7 и EBS Applications 11.5.10.

У меня плохо работает пользовательское представление, которое включает в себя базовое представление Oracle EBS APPS.RA_CUSTOMER_TRX. Это базовое представление против базовой таблицы RA_CUSTOMER_TRX_ALL, как показано ниже.

FROM RA_CUSTOMER_TRX_ALL
     WHERE NVL (
               ORG_ID,
               NVL (
                   TO_NUMBER (
                       DECODE (SUBSTRB (USERENV ('CLIENT_INFO'), 1, 1),
                               ' ', NULL,
                               SUBSTRB (USERENV ('CLIENT_INFO'), 1, 10))),
                   -99)) =
           NVL (
               TO_NUMBER (
                   DECODE (SUBSTRB (USERENV ('CLIENT_INFO'), 1, 1),
                           ' ', NULL,
                           SUBSTRB (USERENV ('CLIENT_INFO'), 1, 10))),
               -99);

Когда я запускаю Oracle Tuning Advisor из Toad для sql моего пользовательского представления, он сообщает мне

1- Restructure SQL finding (see plan 1 in explain plans section)
----------------------------------------------------------------
  The predicate NVL("RA_CUSTOMER_TRX_ALL"."ORG_ID",NVL(TO_NUMBER(DECODE(SUBSTRB
  (USERENV('CLIENT_INFO'),1,1),' ',NULL,SUBSTRB(USERENV('CLIENT_INFO'),1,10))),
  (-99)))=NVL(TO_NUMBER(DECODE(SUBSTRB(USERENV('CLIENT_INFO'),1,1),'
  ',NULL,SUBSTRB(USERENV('CLIENT_INFO'),1,10))),(-99)) used at line ID 53 of
  the execution plan contains an expression on indexed column "ORG_ID". This 
  expression prevents the optimizer from efficiently using indices on table
  "AR"."RA_CUSTOMER_TRX_ALL".

  Recommendation
  --------------
  - Rewrite the predicate into an equivalent form to take advantage of
    indices. Alternatively, create a function-based index on the expression.

  Rationale
  ---------
    The optimizer is unable to use an index if the predicate is an inequality
    condition or if there is an expression or an implicit data type conversion
    on the indexed column.

Таким образом, у меня есть варианты: 1) переписать пользовательское представление, чтобы оно соответствовало базовой таблице вместо базового, или 2) создать индекс на основе функций. Я попытался создать индекс, основанный на функциях, но он говорит мне, что «только чистые функции могут быть проиндексированы».

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

Спасибо.

1 Ответ

0 голосов
/ 29 апреля 2018

NVL не закорачивает, поэтому все ваше выражение всегда оценивается целиком, включая три вызова USERENV. Мне также не ясно, как будет выглядеть формат вашей строки CLIENT_INFO. Я предполагаю, что это число или пробел. Я не совсем понял это, но не могли бы вы изменить предложение where на что-то более похожее на:

WHERE ( org_id IS NOT NULL AND USERENV ('CLIENT_INFO') IS NOT NULL AND
        org_id = TO_NUMBER( USERENV ('CLIENT_INFO')))
   OR ( org_id IS NOT NULL AND USERENV ('CLIENT_INFO') IS NULL AND org_id = -99 )
   OR ( org_id IS NULL AND USERENV ('CLIENT_INFO') IS NULL )

Вы также можете попробовать кэшировать вызов USERENV с помощью общего табличного выражения, но я не уверен, что это поможет:

WITH clientinfo AS (
    SELECT /*+ MATERIALIZE */ USERENV( 'CLIENT_INFO' ) AS client_info FROM dual
)
SELECT ...
  FROM ...
 INNER JOIN clientinfo ci
 WHERE ci.client_info = ...
...