Почему Oracle игнорирует подсказку USE_NL_WITH_INDEX? - PullRequest
0 голосов
/ 06 мая 2020

имея sql для объединения большой таблицы (232 млн записей) с GTT по индексу. объяснение выглядит следующим образом:

4 NESTED LOOPS
  ( Estim. Costs = 439,300 , Estim. #Rows = 548,275 )
  Estim. CPU-Costs = 3,642,574,678 Estim. IO-Costs = 438,956

    1 INDEX FAST FULL SCAN ZTRM_REXP_PRESEL~0
      ( Estim. Costs = 336 , Estim. #Rows = 548,275 )
      Estim. CPU-Costs = 3,432,714 Estim. IO-Costs = 336
    3 TABLE ACCESS BY INDEX ROWID BATCHED TEXT_REXP_ITEM
      ( Estim. Costs = 1 , Estim. #Rows = 1 )
      Estim. CPU-Costs = 6,637 Estim. IO-Costs = 1
      Filter Predicates

        2 INDEX RANGE SCAN TEXT_REXP_ITEM~Y01
          ( Estim. Costs = 1 , Estim. #Rows = 1 )
          Search Columns: 3
          Estim. CPU-Costs = 4,523 Estim. IO-Costs = 1
          Access Predicates

показывает неправильные оценки из-за использования GTT. цель состоит в том, чтобы сначала сделать вложенный l oop для index (2) и gtt (1) и только затем получить доступ к самой таблице (3). по какой-то причине подсказка USE_NL_WITH_INDEX ("TEXT_REXP_ITEM" "TEXT_REXP_ITEM ~ Y01") просто игнорируется. любые идеи, почему?

(1) состоит из

EXPOSURE_ID
VERSION

(2) состоит из

Column Name                     #Distinct

MANDT                                            1
ZZHEAD_EXPOSURE_ID                         251,454
ZZHEAD_VERSION                               3,217
ZZHEAD_ATTRIBUTE_DH01                        1,691
EXT_ITEM_ID                                    823
ZZHEAD_ATTRIBUTE_LH01                            3
ZZHEAD_RELEASE_STATE                             1

(1) и (2) объединены с помощью extension_id и поля версии

текстовое объяснение

|   3 |    NESTED LOOPS                        |                    |   548K|   135M|   439K  (1)| 00:00:18 |
|   4 |     INDEX FAST FULL SCAN               | ZTRM_REXP_PRESEL~0 |   548K|    16M|   336   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS BY INDEX ROWID BATCHED| TEXT_REXP_ITEM     |     1 |   228 |     1   (0)| 00:00:01 |
|*  6 |      INDEX RANGE SCAN                  | TEXT_REXP_ITEM~Y01 |     1 |       |     1   (0)| 00:00:01 |

спасибо

1 Ответ

2 голосов
/ 07 мая 2020

Оптимизатор подчиняется подсказке. Как в документах говорится: :

Подсказка USE_NL_WITH_INDEX инструктирует оптимизатору присоединить указанную таблицу к другому источнику строки с помощью соединения вложенных циклов, используя указанную таблицу в качестве внутренней таблицы

Во вложенном l oop внешняя таблица является первой доступной. Внутренний стол - второй.

Итак, план использует ZTRM_REXP_PRESEL~0 в качестве внешней таблицы. И TEXT_REXP_ITEM как внутренняя таблица. Это именно то, о чем вы просили!

Создание аналогичного примера и использование Oracle Database 19 c механизм подсказок показывает, что подсказка соблюдается:

create table t1 (
  c1 int
);
create table t2 (
  c1 int, c2 varchar2(100)
);

create index i1
  on t1 ( c1 );

create index i2
  on t2 ( c1 );

insert into t1 values ( 1, 'stuff' );

insert into t2
with rws as (
  select level x from dual
  connect by level <= 1000
)
  select x, rpad ( 'stuff', 100, 'f' ) 
  from   rws;

exec dbms_stats.gather_table_stats ( user, 't1' ) ;
exec dbms_stats.gather_table_stats ( user, 't2' ) ;

set serveroutput off
select /*+ USE_NL_WITH_INDEX ( T2 I2 ) */* 
from   t1
join   t2
on     t1.c1 = t2.c1;

select * 
from   table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +HINT_REPORT'));

Plan hash value: 3271411982                                                    

---------------------------------------------                                  
| Id  | Operation                    | Name |                                  
---------------------------------------------                                  
|   0 | SELECT STATEMENT             |      |                                  
|   1 |  NESTED LOOPS                |      |                                  
|   2 |   NESTED LOOPS               |      |                                  
|   3 |    INDEX FULL SCAN           | I1   |                                  
|   4 |    INDEX RANGE SCAN          | I2   |                                  
|   5 |   TABLE ACCESS BY INDEX ROWID| T2   |                                  
---------------------------------------------                                  

Hint Report (identified by operation id / Query Block Name / Object Alias):    
Total hints for statement: 1                                                   
---------------------------------------------------------------------------    

   4 -  SEL$58A6D7F6 / T2@SEL$1                                                
           -  USE_NL_WITH_INDEX ( T2 I2 )
...