2017-12-20 23 views
0

내가 심하게 수행하는 다음 쿼리를 가지고 :오라클 SQL

select 
    distinct 
    u.uuid 
    u.user_name, 
    u.key 

    from request req 
     join int_user u on u.uuid = req.user_uuid 
     join int_right r on r.uuid = req.right_uuid 

    where r.uuid in (
      select r2.uuid from int_right r2 
        where 
          (
           lower(r2.right_name) like '%keyword%' 
           or lower(r2.right_key) like '%keyword%' 
          ) 

        ) 

하위 쿼리는 상관이며 보통 때때로 한 행, 몇 행을 반환합니다. 이제 내가 하위 쿼리를 가져 와서 별도로 실행 한 다음 결과 목록을 가져 와서 정적으로 추가하면 IN 연산자를 외부 쿼리에 추가하면 실행 시간이 3-6s에서 매우 단축됩니다. ~ 0.05s.

r.uuid in ('value1', 'value2', 'value3') 

어떻게 하위 쿼리를 실행 한 다음 결과 집합을 외부 쿼리에 적용 할 수 있습니까?

몇 가지 참고 사항 : - 주위 7mln 행

  • Int_right 테이블 - 보인다 실행 계획에서 약 100K 행
  • - 약 10K 행

  • Int_user 테이블

    • 요청 테이블은 거대하다 오라클은 모든 테이블에서 전체 검사를 수행합니다. 요청 테이블에서 비용과 카디널리티가 매우 큽니다. 서브 쿼리가 특정 검색 조건에 대해 단일 행을 반환하더라도 쿼리가 여전히 느리다는 것을 의미합니다. IN 연산자와 연산자는 매우 빨라지고 낮은 비용. 이 경우 oracle은 int_right 테이블에서 전체 스캔 만 수행하고 다른 테이블에서는 고유 또는 범위 스캔을 수행합니다.

      외부 쿼리에 조건을 직접 추가하거나 존재하는 쿼리 또는 상관 된 하위 쿼리와 같은 다른 쿼리를 시도했지만 어떤 경우에도 여전히 느립니다.

  • +0

    오타를 유감스럽게 생각합니다. 고침, 고마워. –

    +0

    하위 쿼리가 필요한 이유는 무엇입니까? 하위 쿼리의 where 절을 외부 쿼리의 where 절로 사용할 수있는 것 같습니다. – Boneist

    +0

    사실, 대부분의 경우 외부 쿼리에서 where 절을 사용하면 동일한 성능을 얻습니다. 검색 기준이 길면 (20-30 자) 하위 쿼리로 성능이 향상됩니다. –

    답변

    2

    왜 하위 쿼리가 필요합니까?

    같은 조건은 2 개 가지 방법으로 적용 할 수 있습니다

    에서이

    select 
        distinct 
        u.uuid 
        u.user_name, 
        u.key 
    
        from request req 
         join int_user u on u.uuid = req.user_uuid 
         join int_right r on r.uuid = req.right_uuid 
        Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%') 
    

    이 모두 훨씬 더 빠른 쿼리하지만 발생합니다 어디에서

    select 
        distinct 
        u.uuid 
        u.user_name, 
        u.key 
    
        from request req 
         join int_user u on u.uuid = req.user_uuid 
         join int_right r on r.uuid = req.right_uuid 
         And (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%') 
    

    가입 나는 어느 것이 더 빠를 것인지 100 % 확신하지 못한다. 내 이해에서 조인에있는 사람이 더 빠를 것입니다 ...

    +0

    답장을 보내 주셔서 감사하지만 이미 시도했지만 성능을 향상 시키지는 않습니다. 나는 검색 조건이 작을 때 같은 성능을 얻지 만, (20-30 chars와 같이) 더 크면 성능이 서브 쿼리와 더 잘 어울려서 설명 할 수 없다. –

    +0

    @DimaSendrea 조인에 대한 인덱스가 있는가? 기준? 또한 도움이된다면'where exists'를 시도하십시오. [http://www.dba-oracle.com/t_exists_clause_vs_in_clause.htm]. – pOrinG

    0

    일반적으로 코드에 근본적인 결함이없는 경우 (예 : 조인 조건 누락 등) 텍스트를보고 튜닝 할 수 없습니다.Oracle의 경우, 진행하는 가장 생산적인 방법 중 하나는 다음과 같습니다

    1)는이 실행 계획 지표를 얻기 위해 다음과 같은 실행)

    select /*+ gather_plan_statistics */ ... <rest of query> 
    

    이 다음과 같이 추가 힌트와 함께 문제가있는 문을 실행

    select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')) 
    
    당신 것

    그 방법 :

    a)에 사용 된 실제 실행 계획을 참조

    b) 계획의 각 단계에 대한 예상/실제 행 원본 수를 얻습니다. 추정값과 실제 값이 일치하지 않으면 일반적으로 옵티 마이저가 작업 할 정보가 충분하지 않거나 정확하지 않기 때문에주의를 기울일 필요가 있습니다. 6 행에 예를

    SQL> select /*+ gather_plan_statistics */ count(dname) 
        2 from scott.emp e, scott.dept d 
        3 where e.sal <= 1500 
        4 and d.deptno = e.deptno; 
    
    COUNT(DNAME) 
    ------------ 
          7 
    
    1 row selected. 
    
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')); 
    
    PLAN_TABLE_OUTPUT 
    --------------------------------------------------------------------------------------------------- 
    SQL_ID c1cb4s8b141h8, child number 0 
    ------------------------------------- 
    select /*+ gather_plan_statistics */ count(dname) from scott.emp e, 
    scott.dept d where e.sal <= 1500 and d.deptno = e.deptno 
    
    Plan hash value: 3037575695 
    
    --------------------------------------------------------------------------------------------------- 
    | Id | Operation      | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | 
    --------------------------------------------------------------------------------------------------- 
    | 0 | SELECT STATEMENT    |   |  1 |  |  1 |00:00:00.01 |  9 | 
    | 1 | SORT AGGREGATE    |   |  1 |  1 |  1 |00:00:00.01 |  9 | 
    | 2 | MERGE JOIN     |   |  1 |  3 |  7 |00:00:00.01 |  9 | 
    | 3 | TABLE ACCESS BY INDEX ROWID| DEPT |  1 |  4 |  4 |00:00:00.01 |  2 | 
    | 4 |  INDEX FULL SCAN   | DEPT_PK |  1 |  4 |  4 |00:00:00.01 |  1 | 
    |* 5 | SORT JOIN     |   |  4 |  3 |  7 |00:00:00.01 |  7 | 
    |* 6 |  TABLE ACCESS FULL   | EMP  |  1 |  3 |  7 |00:00:00.01 |  7 | 
    --------------------------------------------------------------------------------------------------- 
    
    Predicate Information (identified by operation id): 
    --------------------------------------------------- 
    
        5 - access("D"."DEPTNO"="E"."DEPTNO") 
         filter("D"."DEPTNO"="E"."DEPTNO") 
        6 - filter("E"."SAL"<=1500) 
    

    를 들어

    , 당신은 최적화 3 행을 추정 실제로 7. 큰 차이는 조사 영역을 표시 돌아 왔을 수있다.