Sql 性能调整或替换为distinct子句

Sql 性能调整或替换为distinct子句,sql,oracle,sql-tuning,Sql,Oracle,Sql Tuning,我有一个带有不同子句的查询: SELECT -- /*+ first_rows */ distinct a.sub_id, b.status, pkg_sp_subbrief.get_sub_typ (a.sub_id) sub_type, c.svc_provider_nm, fn_sp_get_svc_plan (a.sub_id) svc_plan, pkg_sp_subbrief.get_

我有一个带有不同子句的查询:

SELECT      --  /*+ first_rows  */
     distinct   a.sub_id, b.status,
            pkg_sp_subbrief.get_sub_typ (a.sub_id) sub_type,
            c.svc_provider_nm, fn_sp_get_svc_plan (a.sub_id) svc_plan,
            pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                    'contact.name.salutation'
                                    ) salutation,
            pkg_sp_subbrief.get_sub_contact_parm
                                        (a.sub_id,
                                        'first_name'
                                        ) first_name,
            pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                        'contact.name.middle'
                                    ) middle_name,
            pkg_sp_subbrief.get_sub_contact_parm
                                        (a.sub_id,
                                            'last_name'
                                        ) last_name,
            pkg_sp_subbrief.get_sub_parm (a.sub_id, 'company_name') company_name,
            pkg_sp_subbrief.get_sub_parm (a.sub_id, 'itc_account') itc_accout,
            pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                        'phones.home.number'
                                    ) phone_number,
            pkg_sp_subbrief.get_location_parm
                                        (a.sub_id,
                                            'address_1'
                                        ) addr_home_address,
            pkg_sp_subbrief.get_location_parm
                                                (a.sub_id,
                                                'city'
                                                ) addr_home_city,
            pkg_sp_subbrief.get_location_parm
                                                (a.sub_id,
                                                'prov'
                                                ) addr_home_prov,
            pkg_sp_subbrief.get_location_parm
                                    (a.sub_id,
                                        'postal_cd'
                                    ) addr_home_postal_code,
            pkg_sp_subbrief.get_location_parm
                                            (a.sub_id,
                                            'country'
                                            ) addr_home_country,
            e.val cm_mta_mac, ' ' telephone_number,
            pkg_sp_subbrief.get_subsvc_parm_first (a.sub_id,
                                                    3374
                                                    ) alpha_tag,
            NVL (j.voipdn1, ' ') voip_dn1,
            NVL (j.mtavoiceport, ' ') mta_voice_port
        FROM svc_provider c,
            ref_status b,
            sub a,
            sub_svc d,
            sub_svc_parm e,
            (SELECT f.sub_id, g.val voipdn1, i.val mtavoiceport
                FROM sub_svc f, sub_svc_parm g, sub_svc_parm i
                WHERE f.svc_id = SvcId('smp_dial_tone_access')
                AND f.sub_svc_status_id ! = 29
                AND f.sub_svc_id = g.sub_svc_id
                AND g.parm_id = get_cgo_parm_id('voip_dn1', GET_CLASS_ID('SubSvcSpec'), SvcID('smp_dial_tone_access'))
                AND f.sub_svc_id = i.sub_svc_id
                AND i.parm_id = 20410) j
        WHERE a.svc_provider_id = c.svc_provider_id
        AND a.sub_status_id = b.status_id
        AND a.sub_id = d.sub_id
        AND d.sub_svc_id = e.sub_svc_id
        AND (e.parm_id = 1254 OR e.parm_id = 20249)
        AND d.sub_svc_status_id != 29
        AND a.sub_status_id != 9
        AND a.sub_id = j.sub_id(+);
此查询返回10146行,执行时间几乎为135秒

对此的解释计划是:

Execution Plan
----------------------------------------------------------
Plan hash value: 2622307916

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name             | Rows  |     Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                  | 10409 |      1118K|       |  2540   (4)| 00:00:31 |
|   1 |  HASH UNIQUE                     |                  | 10409 |      1118K|  1240K|  2540   (4)| 00:00:31 |
|*  2 |   HASH JOIN RIGHT OUTER          |                  | 10409 |      1118K|       |  2279   (4)| 00:00:28 |
|   3 |    VIEW                          |                  |   899 |     23374 |       |  1340   (6)| 00:00:17 |
|*  4 |     HASH JOIN                    |                  |   899 |     53940 |       |  1340   (6)| 00:00:17 |
|*  5 |      HASH JOIN                   |                  |   885 |     35400 |       |   918   (8)| 00:00:12 |
|*  6 |       TABLE ACCESS BY INDEX ROWID| SUB_SVC          |   877 |     17540 |       |   434   (0)| 00:00:06 |
|*  7 |        INDEX RANGE SCAN          | SUB_SVC_IX2      |   951 |           |       |     3   (0)| 00:00:01 |
|*  8 |       TABLE ACCESS FULL          | SUB_SVC_PARM     |  1770 |     35400 |       |   483  (14)| 00:00:06 |
|*  9 |      TABLE ACCESS FULL           | SUB_SVC_PARM     |  2632 |     52640 |       |   422   (2)| 00:00:06 |
|* 10 |    HASH JOIN                     |                  | 10409 |       853K|       |   939   (2)| 00:00:12 |
|* 11 |     TABLE ACCESS FULL            | REF_STATUS       |    95 |      2280 |       |     3   (0)| 00:00:01 |
|* 12 |     HASH JOIN                    |                  | 10409 |       609K|       |   935   (2)| 00:00:12 |
|  13 |      VIEW                        | index$_join$_001 |    49 |       588 |       |     3  (34)| 00:00:01 |
|* 14 |       HASH JOIN                  |                  |       |           |       |            |          |
|  15 |        INDEX FAST FULL SCAN      | SVC_PROVIDER_PK  |    49 |       588 |       |     1   (0)| 00:00:01 |
|  16 |        INDEX FAST FULL SCAN      | SVC_PROVIDER_UK1 |    49 |       588 |       |     1   (0)| 00:00:01 |
|* 17 |      HASH JOIN                   |                  | 10409 |       487K|       |   932   (2)| 00:00:12 |
|* 18 |       TABLE ACCESS FULL          | SUB              |  8777 |       111K|       |    53   (0)| 00:00:01 |
|* 19 |       HASH JOIN                  |                  | 10607 |       362K|       |   878   (2)| 00:00:11 |
|* 20 |        TABLE ACCESS FULL         | SUB_SVC_PARM     | 10607 |       207K|       |   423   (2)| 00:00:06 |
|* 21 |        TABLE ACCESS FULL         | SUB_SVC          | 90284 |      1322K|       |   454   (1)| 00:00:06 |
-----------------------------------------------------------------------------------------------------------------

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

2 - access("A"."SUB_ID"="J"."SUB_ID"(+))
4 - access("F"."SUB_SVC_ID"="I"."SUB_SVC_ID")
5 - access("F"."SUB_SVC_ID"="G"."SUB_SVC_ID")
6 - filter("F"."SUB_SVC_STATUS_ID"<>29)
7 - access("F"."SVC_ID"="SVCID"('smp_dial_tone_access'))
8 - filter("G"."PARM_ID"="GET_CGO_PARM_ID"('voip_dn1',"GET_CLASS_ID"  ('SubSvcSpec'),"SVCID"('smp_dial_tone_access')))
9 - filter("I"."PARM_ID"=20410)
10 - access("A"."SUB_STATUS_ID"="B"."STATUS_ID")
11 - filter("B"."STATUS_ID"<>9)
12 - access("A"."SVC_PROVIDER_ID"="C"."SVC_PROVIDER_ID")
14 - access(ROWID=ROWID)
17 - access("A"."SUB_ID"="D"."SUB_ID")
18 - filter("A"."SUB_STATUS_ID"<>9)
19 - access("D"."SUB_SVC_ID"="E"."SUB_SVC_ID")
20 - filter("E"."PARM_ID"=1254 OR "E"."PARM_ID"=20249)
21 - filter("D"."SUB_SVC_STATUS_ID"<>29)

Statistics
----------------------------------------------------------

   470461  recursive calls
        0  db block gets
 13591783  consistent gets
        0  physical reads
        0  redo size
  1272441  bytes sent via SQL*Net to client
     7960  bytes received via SQL*Net from client
      678  SQL*Net roundtrips to/from client
        0  sorts (memory)
        0  sorts (disk)
    10146  rows processed
执行计划
----------------------------------------------------------
计划哈希值:2622307916
-----------------------------------------------------------------------------------------------------------------
|Id |操作|名称|行|字节|临时SPC |成本(%CPU)|时间|
-----------------------------------------------------------------------------------------------------------------
|0 | SELECT语句| 10409 | 1118K | | 2540(4)| 00:00:31|
|1 |散列唯一| 10409 | 1118K 1240K | 2540(4)| 00:00:31|
|*2 | HASH JOIN RIGHT OUTER | 10409 | 1118K | 2279(4)| 00:00:28|
|3 |视图| 899 | 23374 | 1340(6)| 00:00:17|
|*4 | HASH JOIN | 899 | 53940 | | 1340(6)| 00:00:17|
|*5 | HASH JOIN | 885 | 35400 | | 918(8)| 00:00:12|
|*6 |按索引ROWID访问表| SUB|SVC | 877 | 17540 | 434(0)| 00:00:06|
|*7 |索引范围扫描| SUB | SVC | IX2 | 951 | | 3(0)| 00:00:01|
|*8 |表格访问完整| SUB|U SVC|U PARM | 1770 | 35400 | 483(14)| 00:00:06|
|*9 |表访问完整| SUB|U SVC|U PARM | 2632 | 52640 | 422(2)| 00:00:06|
|*10 |散列连接| 10409 | 853K | | 939(2)| 00:00:12|
|*11 |表格访问完整|参考状态| 95 | 2280 | 3(0)| 00:00:01|
|*12 |散列连接| | 10409 | 609K | | 935(2)| 00:00:12|
|13 |查看|索引|加入| 001 | 49 | 588 | 3(34)| 00:00:01|
|*14 |散列连接| | | | | ||
|15 |索引快速全扫描| SVC |提供程序| PK | 49 | 588 | 1(0)| 00:00:01|
|16 |索引快速全扫描| SVC | U提供程序| UK1 | 49 | 588 | 1(0)| 00:00:01|
|*17 |散列连接| 10409 | 487K | | 932(2)| 00:00:12|
|*18 |表访问完整|子| 8777 | 111K | 53(0)| 00:00:01|
|*19 | HASH JOIN | 10607 | 362K | | 878(2)| 00:00:11|
|*20 |表访问完整|子| SVC | u PARM | 10607 | 207K | 423(2)00:00:06|
|*21 |表访问完整|子| SVC | 90284 | 1322K | 454(1)| 00:00:06|
-----------------------------------------------------------------------------------------------------------------
谓词信息(由操作id标识):
---------------------------------------------------
2-访问(“A”。“SUB_ID”=“J”。“SUB_ID”(+))
4-访问(“F”“SUB_SVC_ID”=“I”“SUB_SVC_ID”)
5-访问(“F”“SUB_SVC_ID”=“G”“SUB_SVC_ID”)
6-过滤器(“F.”子SVC_状态_ID”29)
7-访问(“F”。“SVC\U ID”=“SVID”(“smp\U拨号音\U访问”))
8-过滤器(“G”。“PARM_ID”=“GET_CGO_PARM_ID”(“voip_dn1”)、“GET_CLASS_ID”(“SubSvcSpec”)、“SVCID”(“smp拨号音访问”))
9-过滤器(“I”。“PARM_ID”=20410)
10-访问(“A”“SUB_STATUS_ID”=“B”“STATUS_ID”)
11-过滤器(“B.”状态_ID“9)
12-访问(“A”。“SVC\U提供程序\U ID”=“C”。“SVC\U提供程序\U ID”)
14-访问(ROWID=ROWID)
17-访问(“A”“SUB_ID”=“D”“SUB_ID”)
18-过滤器(“A”。“子”状态“ID”9)
19-访问(“D”。“SUB_SVC_ID”=“E”。“SUB_SVC_ID”)
20-过滤器(“E”。“PARM_ID”=1254或“E”。“PARM_ID”=20249)
21-过滤器(“D”。“SUB_SVC_状态_ID”29)
统计
----------------------------------------------------------
470461递归调用
0 db块获取
13591783
0次物理读取
0重做大小
1272441字节通过SQL*Net发送到客户端
通过SQL*Net从客户端接收7960字节
678 SQL*Net往返于客户端
0排序(内存)
0排序(磁盘)
已处理10146行
当我从查询中删除distinct子句时,它将在4秒内执行,但查询返回10163行,这意味着它也返回重复的行

这是没有明确条款的执行计划:

 Execution Plan
 ----------------------------------------------------------
 Plan hash value: 3514824003

---------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                  | 10409 |  3608K|  2279   (4)| 00:00:28 |
|*  1 |  HASH JOIN RIGHT OUTER          |                  | 10409 |  3608K|  2279   (4)| 00:00:28 |
|   2 |   VIEW                          |                  |   899 |   237K|  1340   (6)| 00:00:17 |
|*  3 |    HASH JOIN                    |                  |   899 | 53940 |  1340   (6)| 00:00:17 |
|*  4 |     HASH JOIN                   |                  |   885 | 35400 |   918   (8)| 00:00:12 |
|*  5 |      TABLE ACCESS BY INDEX ROWID| SUB_SVC          |   877 | 17540 |   434   (0)| 00:00:06 |
|*  6 |       INDEX RANGE SCAN          | SUB_SVC_IX2      |   951 |       |     3   (0)| 00:00:01 |
|*  7 |      TABLE ACCESS FULL          | SUB_SVC_PARM     |  1770 | 35400 |   483  (14)| 00:00:06 |
|*  8 |     TABLE ACCESS FULL           | SUB_SVC_PARM     |  2632 | 52640 |   422   (2)| 00:00:06 |
|*  9 |   HASH JOIN                     |                  | 10409 |   853K|   939   (2)| 00:00:12 |
|* 10 |    TABLE ACCESS FULL            | REF_STATUS       |    95 |  2280 |     3   (0)| 00:00:01 |
|* 11 |    HASH JOIN                    |                  | 10409 |   609K|   935   (2)| 00:00:12 |
|  12 |     VIEW                        | index$_join$_001 |    49 |   588 |     3  (34)| 00:00:01 |
|* 13 |      HASH JOIN                  |                  |       |       |            |          |
|  14 |       INDEX FAST FULL SCAN      | SVC_PROVIDER_PK  |    49 |   588 |     1   (0)| 00:00:01 |
|  15 |       INDEX FAST FULL SCAN      | SVC_PROVIDER_UK1 |    49 |   588 |     1   (0)| 00:00:01 |
|* 16 |     HASH JOIN                   |                  | 10409 |   487K|   932   (2)| 00:00:12 |
|* 17 |      TABLE ACCESS FULL          | SUB              |  8777 |   111K|    53   (0)| 00:00:01 |
|* 18 |      HASH JOIN                  |                  | 10607 |   362K|   878   (2)| 00:00:11 |
|* 19 |       TABLE ACCESS FULL         | SUB_SVC_PARM     | 10607 |   207K|   423   (2)| 00:00:06 |
|* 20 |       TABLE ACCESS FULL         | SUB_SVC          | 90284 |  1322K|   454   (1)| 00:00:06 |
----------------------------------------------------------------------------------------------------


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

 1 - access("A"."SUB_ID"="J"."SUB_ID"(+))
 3 - access("F"."SUB_SVC_ID"="I"."SUB_SVC_ID")
 4 - access("F"."SUB_SVC_ID"="G"."SUB_SVC_ID")
 5 - filter("F"."SUB_SVC_STATUS_ID"<>29)
 6 - access("F"."SVC_ID"="SVCID"('smp_dial_tone_access'))
 7 - filter("G"."PARM_ID"="GET_CGO_PARM_ID"('voip_dn1',"GET_CLASS_ID"  ('SubSvcSpec'),"SVCID"('smp_dial_tone_access')))
 8 - filter("I"."PARM_ID"=20410)
 9 - access("A"."SUB_STATUS_ID"="B"."STATUS_ID")
10 - filter("B"."STATUS_ID"<>9)
11 - access("A"."SVC_PROVIDER_ID"="C"."SVC_PROVIDER_ID")
13 - access(ROWID=ROWID) 
16 - access("A"."SUB_ID"="D"."SUB_ID")
17 - filter("A"."SUB_STATUS_ID"<>9)  
18 - access("D"."SUB_SVC_ID"="E"."SUB_SVC_ID")
19 - filter("E"."PARM_ID"=1254 OR "E"."PARM_ID"=20249)
20 - filter("D"."SUB_SVC_STATUS_ID"<>29)


Statistics
----------------------------------------------------------
   470461  recursive calls
        0  db block gets
 13592455  consistent gets
        0  physical reads
        0  redo size
  1168343  bytes sent via SQL*Net to client
     7971  bytes received via SQL*Net from client
      679  SQL*Net roundtrips to/from client
        0  sorts (memory)
        0  sorts (disk)
    10163  rows processed
执行计划
----------------------------------------------------------
计划哈希值:3514824003
---------------------------------------------------------------------------------------------------
|Id |操作|名称|行|字节|成本(%CPU)|时间|
----------------------------------------------------------------------------------------------------
|0 | SELECT语句| 10409 | 3608K | 2279(4)| 00:00:28|
|*1 | HASH JOIN RIGHT OUTER | 10409 | 3608K | 2279(4)| 00:00:28|
|2 |视图| 899 | 237K | 1340(6)| 00:00:17|
|*3 |散列连接| 899 | 53940 | 1340(6)| 00:00:17|
|*4 |散列连接| 885 | 35400 | 918(8)| 00:00:12|
|*5 |按索引ROWID访问表| SUB|SVC | 877 | 17540 | 434(0)| 00:00:06|
|*6 |索引范围扫描| SUB | SVC | IX2 | 951 | 3(0)| 00:00:01|
|*7 |表格访问完整| SUB|U SVC|U PARM | 1770 | 35400 | 483(14)| 00:00:06|
|*
SELECT *, pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                    'contact.name.salutation'
                                    ) salutation,
            pkg_sp_subbrief.get_sub_contact_parm
                                        (a.sub_id,
                                        'first_name'
                                        ) first_name,
            pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                        'contact.name.middle'
                                    ) middle_name,
            pkg_sp_subbrief.get_sub_contact_parm
                                        (a.sub_id,
                                            'last_name'
                                        ) last_name,
            pkg_sp_subbrief.get_sub_parm (a.sub_id, 'company_name') company_name,
            pkg_sp_subbrief.get_sub_parm (a.sub_id, 'itc_account') itc_accout,
            pkg_sp_subbrief.get_sub_contact_parm
                                    (a.sub_id,
                                        'phones.home.number'
                                    ) phone_number,
            pkg_sp_subbrief.get_location_parm
                                        (a.sub_id,
                                            'address_1'
                                        ) addr_home_address,
            pkg_sp_subbrief.get_location_parm
                                                (a.sub_id,
                                                'city'
                                                ) addr_home_city,
            pkg_sp_subbrief.get_location_parm
                                                (a.sub_id,
                                                'prov'
                                                ) addr_home_prov,
            pkg_sp_subbrief.get_location_parm
                                    (a.sub_id,
                                        'postal_cd'
                                    ) addr_home_postal_code,
            pkg_sp_subbrief.get_location_parm
                                            (a.sub_id,
                                            'country'
                                            ) addr_home_country,\
            pkg_sp_subbrief.get_subsvc_parm_first (a.sub_id,
                                                    3374
                                                    ) alpha_tag,
            fn_sp_get_svc_plan (a.sub_id) svc_plan,
            pkg_sp_subbrief.get_sub_typ (a.sub_id) sub_type
FROM (                                          
    SELECT      --  /*+ first_rows  */
         distinct   a.sub_id, b.status,
                c.svc_provider_nm,
                e.val cm_mta_mac, ' ' telephone_number,
                NVL (j.voipdn1, ' ') voip_dn1,
                NVL (j.mtavoiceport, ' ') mta_voice_port
            FROM svc_provider c,
                ref_status b,
                sub a,
                sub_svc d,
                sub_svc_parm e,
                (SELECT f.sub_id, g.val voipdn1, i.val mtavoiceport
                    FROM sub_svc f, sub_svc_parm g, sub_svc_parm i
                    WHERE f.svc_id = SvcId('smp_dial_tone_access')
                    AND f.sub_svc_status_id ! = 29
                    AND f.sub_svc_id = g.sub_svc_id
                    AND g.parm_id = get_cgo_parm_id('voip_dn1', GET_CLASS_ID('SubSvcSpec'), SvcID('smp_dial_tone_access'))
                    AND f.sub_svc_id = i.sub_svc_id
                    AND i.parm_id = 20410) j
            WHERE a.svc_provider_id = c.svc_provider_id
            AND a.sub_status_id = b.status_id
            AND a.sub_id = d.sub_id
            AND d.sub_svc_id = e.sub_svc_id
            AND (e.parm_id = 1254 OR e.parm_id = 20249)
            AND d.sub_svc_status_id != 29
            AND a.sub_status_id != 9
            AND a.sub_id = j.sub_id(+)
    )