2014-01-10 2 views
0

를 관련하는 쿼리가 여기어떻게 여기 실행 계획 및 SQL 쿼리

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)를 쿼리의 일부 원인이있다?

편집

내 실수는, 좀 더 명확하고 있어야합니다. 이제 실행 계획의 일부를 쿼리의 일부와 연관시키는 방법을 알아야 할 필요가 있음을 알게되었습니다. 쿼리의 일부

  • TABLE ACCESS(FULL)의 원인이되는 예를

    1. 를 들어 쿼리의 일부 그러나 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' 
    

    은 실행 계획은 당신이 원래 다른 하나에 의해 발생 된 알이 "전체 검사"를 보여줍니다.

    +0

    에 참여해야합니다. 두 경우 모두 하나의 전체 스캔 만 표시됩니다. – bjan

    +0

    이 'UPDATE/* + FULL (c) FULL (p) */hrs.rns_recon_ho c SET c.refr_numb ='? –

    +0

    이제 힌트가 내부 쿼리와 함께있을 때 전체 스캔이 두 번 있습니다. 외부 쿼리가'FULL' 스캔을 일으키는 것입니까? – bjan

    0

    나를 다시 보자

    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 
    

    이유 :

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

    지금 당신의 계획을 재현

    최적화 만이 저렴 경우 인덱스를 사용하도록 선택합니다 (이하 읽기). 이는 일반적으로 WHERE 절 조건이 색인의 맨 앞 (즉 가장 왼쪽) 열에 매핑되어야 함을 의미합니다. 따라서 where 절 컬럼에 인덱스 (PROD_CODE, REFR_NUMB, NARR_1)를 추가하면이를 피할 수 있습니다.

    이 하나

    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 
    

    을 확인 확인하려면 그러나 이것은 단지 계획을 변경하는 것입니다,하지만 결코 당신이 준 제한된 입력을, 어떤 성능 향상을 약속합니다.

    FOLLOW UP : 그것은 인덱스를 무시하기 때문에

    는 외부 쿼리는 FTS에 것입니다. 따라서 복합 키를 배치 할 때 인덱스는 곧바로 옵티 마이저에 사용되며 동일한 인덱스가 사용됩니다. 하위 쿼리는 인덱스 된 열의 외부 쿼리와 조인되므로 인덱스를 사용합니다.

    다음 핵심 규칙을 따르면 가능한 실행 계획에 가까울지라도 정확한 계획을 식별하는 방법은 100 %를 달성 할 수 없습니다.

    +0

    내 편집 참조하십시오. – bjan