2012-04-13 6 views
1

나는 오라클에서 SELECT 문이 :이 쿼리 내 환경에서 돌아 약 26 분이 소요Oracle 데이터베이스에서 실행되는 SELECT 문을 최적화하려면 어떻게합니까?

SELECT COUNT(DISTINCT ds1.endpoint_msisdn)     multiple30, 
     dss1.service, 
     dss1.endpoint_provisioning_id, 
     dss1.company_scope, 
     Nvl(x.subscription_status, dss1.subscription_status) subscription_status 
FROM daily_summary ds1 
     join daily_summary ds2 
     ON ds1.endpoint_msisdn = ds2.endpoint_msisdn, 
     daily_summary_static dss1, 
     daily_summary_static dss2, 
     (SELECT NULL subscription_status 
     FROM dual 
     UNION ALL 
     SELECT -2 subscription_status 
     FROM dual) x 
WHERE ds1.summary_ts >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND ds1.summary_ts <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss1.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND dss1.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss2.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
     AND dss2.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
     AND dss1.service <> dss2.service 
     AND (dss1.company_scope = 2 
       OR dss1.company_scope = 5) 
     AND (dss2.company_scope = 2 
       OR dss2.company_scope = 5) 
     AND dss1.company_scope = dss2.company_scope 
     AND ds1.endpoint_noc_id = dss1.endpoint_noc_id 
     AND ds1.endpoint_host_id = dss1.endpoint_host_id 
     AND ds1.endpoint_instance_id = dss1.endpoint_instance_id 
     AND ds2.endpoint_noc_id = dss2.endpoint_noc_id 
     AND ds2.endpoint_host_id = dss2.endpoint_host_id 
     AND ds2.endpoint_instance_id = dss2.endpoint_instance_id 
     AND dss1.endpoint_provisioning_id = dss2.endpoint_provisioning_id 
     AND Least(1, ds1.total_actions) = 1 
     AND Least(1, ds2.total_actions) = 1 
GROUP BY dss1.service, 
      dss1.endpoint_provisioning_id, 
      dss1.company_scope, 
      Nvl(x.subscription_status, dss1.subscription_status); 

을,하지만 난 부분을 제거하는 경우 :

dss1.last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND 
        dss1.last_active <= to_date('10-04-2012','dd-mm-yyyy') AND 
        dss2.last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND 
        dss2.last_active <= to_date('10-04-2012','dd-mm-yyyy') AND 

은 단지 실행하는 데 20 초 걸렸다 .

우리는 last_active 열에 대한 색인을 가지고 있는데 왜이 섹션의 성능이 그렇게 느려지는지 모르겠습니다. 어떤 아이디어?


매우 빠른 답변입니다.

---------------------------------------------------------------------------------------------------------------- 
| Id | Operation        | Name     | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT      |      |  1 | 119 | 204 (3)| 00:00:03 | 
| 1 | SORT GROUP BY       |      |  1 | 119 | 204 (3)| 00:00:03 | 
| 2 | MERGE JOIN CARTESIAN     |      |  1 | 119 | 203 (2)| 00:00:03 | 
|* 3 | TABLE ACCESS BY INDEX ROWID   | DAILY_SUMMARY  |  1 | 27 | 11 (0)| 00:00:01 | 
| 4 |  NESTED LOOPS      |      |  1 | 116 | 199 (3)| 00:00:03 | 
|* 5 |  HASH JOIN       |      |  3 | 267 | 178 (3)| 00:00:03 | 
|* 6 |  HASH JOIN       |      |  1 | 65 | 140 (2)| 00:00:02 | 
| 7 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY_STATIC | 61 | 1647 | 37 (3)| 00:00:01 | 
| 8 |   BITMAP CONVERSION TO ROWIDS  |      |  |  |   |   | 
| 9 |   BITMAP AND      |      |  |  |   |   | 
| 10 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
| 11 |   SORT ORDER BY    |      |  |  |   |   | 
|* 12 |    INDEX RANGE SCAN   | DSS_LAST_ACTIVE  | 560 |  |  3 (0)| 00:00:01 | 
| 13 |   BITMAP OR      |      |  |  |   |   | 
| 14 |   BITMAP CONVERSION FROM ROWIDS|      |  |  |   |   | 
|* 15 |    INDEX RANGE SCAN   | DSS_C_SCOPE_IDX  | 560 |  | 18 (0)| 00:00:01 | 
| 16 |   BITMAP CONVERSION FROM ROWIDS|      |  |  |   |   | 
|* 17 |    INDEX RANGE SCAN   | DSS_C_SCOPE_IDX  | 560 |  |  1 (0)| 00:00:01 | 
| 18 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY  | 1773 | 67374 | 102 (0)| 00:00:02 | 
|* 19 |   INDEX RANGE SCAN    | DS_DAILY_ACTIVE_IDX | 1767 |  | 14 (0)| 00:00:01 | 
| 20 |  TABLE ACCESS BY INDEX ROWID  | DAILY_SUMMARY_STATIC | 61 | 1464 | 37 (3)| 00:00:01 | 
| 21 |  BITMAP CONVERSION TO ROWIDS  |      |  |  |   |   | 
| 22 |   BITMAP AND      |      |  |  |   |   | 
| 23 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
| 24 |   SORT ORDER BY     |      |  |  |   |   | 
|* 25 |   INDEX RANGE SCAN    | DSS_LAST_ACTIVE  | 560 |  |  3 (0)| 00:00:01 | 
| 26 |   BITMAP OR      |      |  |  |   |   | 
| 27 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
|* 28 |   INDEX RANGE SCAN    | DSS_C_SCOPE_IDX  | 560 |  | 18 (0)| 00:00:01 | 
| 29 |   BITMAP CONVERSION FROM ROWIDS |      |  |  |   |   | 
|* 30 |   INDEX RANGE SCAN    | DSS_C_SCOPE_IDX  | 560 |  |  1 (0)| 00:00:01 | 
|* 31 |  INDEX RANGE SCAN     | DS_PKEY    |  8 |  |  2 (0)| 00:00:01 | 
| 32 | BUFFER SORT       |      |  2 |  6 | 193 (3)| 00:00:03 | 
| 33 |  VIEW        |      |  2 |  6 |  4 (0)| 00:00:01 | 
| 34 |  UNION-ALL       |      |  |  |   |   | 
| 35 |  FAST DUAL       |      |  1 |  |  2 (0)| 00:00:01 | 
| 36 |  FAST DUAL       |      |  1 |  |  2 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------------------------- 
+0

그것은 여전히 ​​매우 오랜 시간이 걸릴 :

따라서, 나는 일부러 더 이상 인덱스를 사용할 수 없습니다이 때문에 쿼리 최적화와 같은 블록을 변경하여 인덱스 사용을 해제 제안 ** 조건. 나를 혼란스럽게하는 이유는 dss에서의 날짜 조작이 너무 느리지 만 ds에서 날짜 조작을 할 때가 빠르다는 것입니다. ds의 레코드가 dss보다 훨씬 많았 기 때문에 ... dss의 last_active에 대한 인덱스가 있습니다. –

+0

'last_active'를 비교하는 값은 정적이고 한번만 계산되기 때문에 그 라인들에 강렬한 날짜 조작은 없습니다. 인덱스가 있지만 옵티마이 저가 인덱스를 사용하도록 선택 했습니까? 두 경우의 실행 계획을 추가 할 수 있습니까? –

+0

안녕하세요 Erkan, 설명 계획은 원래 게시물에 추가되었습니다,이 설명은 "천천히"SELECT 문에 대한 모든 전체 테이블 스캔을 볼 수 없습니다, 인덱스 범위 스캔은 인덱스 **에서 일어난 DSS_LAST_ACTIVE **, 돈 왜 그렇게 천천히 돌아가는지. –

답변

2

를 실제로이 부분 때문에 : 너무 느리게 실행하는 이유

select * from daily_summary_static where last_active >= to_date('10-04-2012','dd-mm-yyyy') - 30 AND last_active <= to_date('10-04-2012','dd-mm-yyyy');


모르는, 내가 어떤 전체 테이블이 여기에 스캔이 표시되지 않는 명령문에 대한 계획을 설명 느리게 만듭니다.

AND dss1.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND dss1.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 
AND dss2.last_active >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND dss2.last_active <= To_date('10-04-2012', 'dd-mm-yyyy') 

에 색인이있는 것 같습니다. 0은 사용하지 말아야 할 때, 즉 다른 유용한 색인을 사용하지 못하게 할 때 사용됩니다. 내 내기는 dss1과 dss2에 합류하기 위해 사용되는 다른 색인에 대한 것이지만 실제로는 별 문제가되지 않습니다. 30 - ** 내가 제거 할 때

AND (dss1.last_active+0) >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND (dss1.last_active+0) <= To_date('10-04-2012', 'dd-mm-yyyy') 
AND (dss2.last_active+0) >= To_date('10-04-2012', 'dd-mm-yyyy') - 30 
AND (dss2.last_active+0) <= To_date('10-04-2012', 'dd-mm-yyyy') 
+1

인덱스의 사용이 원인 일 수도 있다고 생각합니다. NO_INDEX 힌트를 사용하여이를 수행 할 수도 있습니다. –

+0

감사합니다. ammoQ. 이것은 정말로 도움이됩니다. 나는 당신이 제안한 것처럼 SQL을 변경했다. 그것은 20 초 만에 끝났다. 한 가지 질문은이 색인이 다른 색인을 어떻게 사용하지 못하게합니까? –

+2

테이블의 통계는 시대에 뒤 떨어진 것일 수 있습니다. –

관련 문제