2014-01-10 5 views
0

Вот запросКак связать план выполнения и SQL Query

UPDATE hrs.rns_recon_ho c SET c.refr_numb = 
(
SELECT seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1 
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0 
) 
Where c.prod_code = 0 And c.refr_numb = 0 
AND c.narr_1 = '3/13/201211013198693442091' 

А вот его план выполнения

enter image description here Какая часть запроса вызывает TABLE ACCESS(FULL)?

Редактировать

Моя ошибка, я должен был быть более ясным. Позвольте мне теперь понять, что мне нужно знать, как связать части плана выполнения с частями запроса. Например

  1. Какая часть запроса является причиной TABLE ACCESS(FULL)
  2. Какая часть запроса вызывает TABLE ACCESS(BY GLOBAL INDEX ROWID)

Тем не менее, очевидно, что INDEX(...)...PROD_CODE вызывается полем PROD_CODE.

Есть ли какое-либо эмпирическое правило, рекомендации или просто трюки для идентификации? Или мы не можем знать, потому что оптимизатор не скажет нам, почему был выбран определенный путь.

+0

Каков ваш основной ключ? Какой у вас индекс? У вас есть разделы? – SriniV

+0

@realspirituals 'seqn_numb' - это PK, все запрошенные поля индексируются и да, таблица разделена. – bjan

+0

Не могли бы вы разместить свою таблицу создания, индексные скрипты? ИЛИ установить его в sqlfiddle.com – SriniV

ответ

0

Возможно, необходимо провести сканирование полного стола с помощью подсказки на одной таблице, например.

UPDATE hrs.rns_recon_ho c SET c.refr_numb = 
(
SELECT /*+ FULL(p) */ seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1 
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0 
) 
Where c.prod_code = 0 And c.refr_numb = 0 
AND c.narr_1 = '3/13/201211013198693442091' 

или

UPDATE /*+ FULL(c) */ hrs.rns_recon_ho c SET c.refr_numb = 
(
SELECT seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1 
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0 
) 
Where c.prod_code = 0 And c.refr_numb = 0 
AND c.narr_1 = '3/13/201211013198693442091' 

В случае, если ваш план выполнения показывает два «Full-Scan» Вы знаете, это было первоначально вызвано другой.

+0

. В обоих случаях отображается только одно полное сканирование. – bjan

+0

Также этим «UPDATE/* + FULL (c) FULL (p) */hrs.rns_recon_ho c SET c.refr_numb ='? –

+0

Теперь есть два полных сканирования, когда подсказка с внутренним запросом. Означает ли это, что внешний запрос вызывает сканирование «FULL»? – bjan

0

Позвольте мне воссоздать:

CREATE TABLE RNS_RECON_HO (PROD_CODE NUMBER, 
      REFR_NUMB NUMBER, 
      NARR_1 VARCHAR2 (25), 
      SEQN_NUMB NUMBER primary key ); 

CREATE INDEX TESTTT ON RNS_RECON_HO (PROD_CODE); 
CREATE INDEX TESTTT1 ON RNS_RECON_HO (REFR_NUMB); 
CREATE INDEX TESTTT2 ON RNS_RECON_HO (NARR_1); 

Теперь воспроизводя свой план:

SET AUTOTRACE ON 

UPDATE 
     RNS_RECON_HO C 
SET 
     C.REFR_NUMB = 
      (SELECT 
       SEQN_NUMB 
      FROM 
       RNS_RECON_HO P 
      WHERE 
        P.NARR_1 = C.NARR_1 
       AND P.SEQN_NUMB = P.REFR_NUMB 
       AND P.PROD_CODE = PROD_CODE) 
WHERE 
     C.PROD_CODE = 0 
     AND C.REFR_NUMB = 0 
     AND C.NARR_1 = '3/13/201211013198693442091'; 


0 rows updated. 

Execution Plan 
---------------------------------------------------------- 
    0  UPDATE STATEMENT Optimizer Mode=ALL_ROWS (Cost=2 Card=1 Bytes=78) 
    1 0 UPDATE RNS_RECON_HO 
    2 1  TABLE ACCESS FULL RNS_RECON_HO (Cost=2 Card=1 Bytes=78) 
    3 1  TABLE ACCESS BY INDEX ROWID RNS_RECON_HO (Cost=5 Card=1 Bytes=91) 
    4 3  INDEX RANGE SCAN TESTTT (Cost=1 Card=1) 

Statistics 
---------------------------------------------------------- 
     190 recursive calls 
      0 spare statistic 3 
      0 gcs messages sent 
     25 db block gets from cache 
      0 physical reads direct (lob) 
      0 queue position update 
      0 queue single row 
      0 queue ocp pages 
      0 HSC OLTP Compressed Blocks 
      0 HSC IDL Compressed Blocks 
      0 rows processed 

Причина:

Оптимизатор выбрать только использовать индекс, если он дешевле (меньше читает), чем сканирование таблицы. Обычно это означает, что критерии WHERE должны сопоставляться с ведущими (то есть самыми левыми) столбцами индекса. Таким образом, добавление индекса (PROD_CODE, REFR_NUMB, NARR_1) в столбцы клаузулов where будет избегать этого.

Для подтверждения проверить это один

CREATE INDEX TESTTT3 ON RNS_RECON_HO (PROD_CODE, REFR_NUMB, NARR_1); 

SET AUTOTRACE ON 

UPDATE 
     RNS_RECON_HO C 
SET 
     C.REFR_NUMB = 
      (SELECT 
       SEQN_NUMB 
      FROM 
       RNS_RECON_HO P 
      WHERE 
        P.NARR_1 = C.NARR_1 
       AND P.SEQN_NUMB = P.REFR_NUMB 
       AND P.PROD_CODE = PROD_CODE) 
WHERE 
     C.PROD_CODE = 0 
     AND C.REFR_NUMB = 0 
     AND C.NARR_1 = '3/13/201211013198693442091'; 

0 rows updated. 

Execution Plan 
---------------------------------------------------------- 
    0  UPDATE STATEMENT Optimizer Mode=ALL_ROWS (Cost=1 Card=1 Bytes=78) 
    1 0 UPDATE RNS_RECON_HO 
    2 1  INDEX RANGE SCAN TESTTT3 (Cost=1 Card=1 Bytes=78) 
    3 1  TABLE ACCESS BY INDEX ROWID RNS_RECON_HO (Cost=27 Card=1 Bytes=91) 
    4 3  INDEX FULL SCAN TESTTT3 (Cost=26 Card=1) 

Statistics 
---------------------------------------------------------- 
      1 recursive calls 
      0 spare statistic 3 
      0 gcs messages sent 
      0 db block gets from cache 
      0 physical reads direct (lob) 
      0 queue position update 
      0 queue single row 
      0 queue ocp pages 
      0 HSC OLTP Compressed Blocks 
      0 HSC IDL Compressed Blocks 
      0 rows processed 

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

ПОСЛЕДУЮЩИЕ:

Внешний запрос происходит FTS, поскольку она игнорирует индекс. Поэтому, когда мы помещаем составной ключ, индекс является прямым для оптимизатора и тот же самый используется. Sub-запрос использует индекс, поскольку он соединен с внешним запросом в индексированном столбце.

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

+0

см. Мое редактирование – bjan

Смежные вопросы