2010-06-30 104 views
1

我问这个question前,但是从意见我意识到这个问题是没有足够的信息的问题得到帮助所以我在这里提供整个查询+说明计划:优化Oracle查询

查询:

WITH gtt_1 AS 
    (SELECT 
    r.user_id, r.role_id, r.participant_code, MAX(status_id) 
    FROM 
    user_role r, 
    cmp_role c 
    WHERE 
    r.role_id = c.role_id 
    AND r.participant_code IS NOT NULL 
    AND c.group_id = 3 
    GROUP BY 
    r.user_id, r.role_id, r.participant_code 
    HAVING MAX(status_id) IN (SELECT b.status_id FROM USER_ROLE b 
           WHERE (b.ACTIVE = 1 OR (b.ACTIVE IN (0,3) 
            AND SYSDATE BETWEEN b.effective_from_date AND b.effective_to_date 
            )) 
          ) 
) 
SELECT c.role_id, 
     c.subgroup, 
     c.subgroup_description, 
     COUNT(a.USER_ID) user_count 
FROM  
    (SELECT b.user_id, b.role_id FROM gtt_1 b, user e 
     WHERE e.user_id = RTRIM(b.user_id) 
     ) a 
RIGHT OUTER JOIN CMP_ROLE c ON a.role_id = c.role_id 
WHERE c.group_id = 3 
GROUP BY c.role_id,c.subgroup,c.subgroup_description 
ORDER BY c.subgroup; 

表中:

SQL> select count(*) from user_role; 

    COUNT(*) 
---------- 
    803513 

SQL> select count(*) from cmp_role; 

    COUNT(*) 
---------- 
     27 

SQL> select count(*) from user; 

    COUNT(*) 
---------- 
    73893 

解释计划:

SQL> select * from table(dbms_xplan.display); 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------------------------------------------------------------- 
Plan hash value: 269840545 

-------------------------------------------------------------------------------------------------------------------------- 
| Id | Operation       | Name    | Rows | Bytes | Cost (%CPU)| Time  | Inst |IN-OUT| 
-------------------------------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT     |     | 256 | 18944 | 1683 (4)| 00:00:21 |  |  | 
| 1 | SORT GROUP BY      |     | 256 | 18944 | 1683 (4)| 00:00:21 |  |  | 
|* 2 | HASH JOIN OUTER     |     | 2776 | 200K| 1682 (4)| 00:00:21 |  |  | 
| 3 | TABLE ACCESS BY INDEX ROWID  | ROLE    |  8 | 504 |  2 (0)| 00:00:01 |  |  | 
|* 4 |  INDEX RANGE SCAN    | N_ROLE_IDX2  |  8 |  |  1 (0)| 00:00:01 |  |  | 
| 5 | VIEW        |     | 9370 | 100K| 1683 (5)| 00:00:21 |  |  | 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------------------------------------------------------------- 
| 6 |  NESTED LOOPS     |     | 9370 | 164K| 1683 (5)| 00:00:21 |  |  | 
| 7 |  VIEW       |     | 9370 | 100K| 1677 (4)| 00:00:21 |  |  | 
|* 8 |  FILTER      |     |  |  |   |   |  |  | 
| 9 |  HASH GROUP BY    |     | 9370 | 283K| 1677 (4)| 00:00:21 |  |  | 
|* 10 |   HASH JOIN     |     | 232K| 7051K| 1654 (3)| 00:00:20 |  |  | 
| 11 |   TABLE ACCESS BY INDEX ROWID| ROLE    |  8 | 56 |  2 (0)| 00:00:01 |  |  | 
|* 12 |   INDEX RANGE SCAN   | N_ROLE_IDX2  |  8 |  |  1 (0)| 00:00:01 |  |  | 
|* 13 |   TABLE ACCESS FULL   | USER_ROLE   | 786K| 17M| 1643 (2)| 00:00:20 |  |  | 
|* 14 |  TABLE ACCESS BY INDEX ROWID | USER_ROLE   |  1 | 30 |  3 (0)| 00:00:01 |  |  | 
|* 15 |   INDEX UNIQUE SCAN   | U_USER_ROLE_IDX1 |  1 |  |  2 (0)| 00:00:01 |  |  | 
| 16 |  REMOTE       | MV_P113PT_USER_HUB |  1 |  7 |  0 (0)| 00:00:01 | HWVAU~ | R->S | 



Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - access("A"."ROLE_ID"(+)="ROLE"."ROLE_ID") 
    4 - access("ROLE"."GRP_ID"=3) 
    8 - filter(EXISTS (SELECT 0 FROM "P181"."USER_ROLE" "USER_ROLE" WHERE "USER_ROLE"."STTS_ID"=:B1 AND 
       (TO_NUMBER("USER_ROLE"."ACTV_CD")=1 OR (TO_NUMBER("USER_ROLE"."ACTV_CD")=0 OR TO_NUMBER("USER_ROLE"."ACTV_CD")=3) 
       AND "USER_ROLE"."EFCTV_TO_DTTM">[email protected]! AND "USER_ROLE"."EFCTV_FROM_DTTM"<[email protected]!))) 
    10 - access("USER_ROLE"."ROLE_ID"="ROLE"."ROLE_ID") 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------------------------------------------------------------- 
    12 - access("ROLE"."GRP_ID"=3) 
    13 - filter("USER_ROLE"."PRTPT_CD" IS NOT NULL) 
    14 - filter(TO_NUMBER("USER_ROLE"."ACTV_CD")=1 OR (TO_NUMBER("USER_ROLE"."ACTV_CD")=0 OR 
       TO_NUMBER("USER_ROLE"."ACTV_CD")=3) AND "USER_ROLE"."EFCTV_TO_DTTM">[email protected]! AND 
       "USER_ROLE"."EFCTV_FROM_DTTM"<[email protected]!) 
    15 - access("USER_ROLE"."STTS_ID"=:B1) 

我没有为TKPROF

回答

0

请问下面的查询产生相同的结果足以priveleges?

SELECT c.role_id 
     , c.subgroup 
     , c.subgroup_description 
     , COUNT(a.USER_ID) user_count 
FROM cmp_role c 
     LEFT OUTER JOIN (
      SELECT r.user_id 
        , r.role_id 
      FROM (
        SELECT r.user_id 
          , r.role_id 
          , r.participant_code 
          , MAX(r.status_id) 
        FROM user_role r 
          INNER JOIN cmp_role c ON c.role_id = r.role_id 
        WHERE r.participant_code IS NOT NULL 
          AND c.group_id = 3 
        GROUP BY 
          r.user_id 
          , r.role_id 
          , r.participant_code 
        HAVING MAX(r.status_id) IN (
           SELECT status_id 
           FROM user_role 
           WHERE (Active = 1 
             OR (Active IN (0,3) 
              AND SYSDATE BETWEEN effective_from_date AND effective_to_date) 
             ) 
          ) 
       ) r 
        INNER JOIN user e ON e.user_id = RTRIM(r.user_id)   
     ) a ON a.role_id = c.role_id   
WHERE c.group_id = 3 
GROUP BY 
     c.role_id 
     , c.subgroup 
     , c.subgroup_description 
ORDER BY 
     c.subgroup 

这是比较容易阅读(对我来说)。如果它产生相同的结果,则可以从内部选择开始删除r.participant_codeMAX(r.status_id)

+0

虽然结果稍微偏离但不是太大。 – Mehur 2010-06-30 15:11:27