oracle sql优化一个案例

时间:2022-04-06 17:04:58

今天帮同学看了一个sql,原sql
SELECT
(select t.product_name from td_b_product t where t.product_id=a.product_id ) as product_name,
(select t1.area_name from td_m_area t1 where t1.area_code=a.city_code) as area_name
FROM uop_crm1.tf_f_user a,
uop_crm1.tf_f_cust_vip b,
uop_crm1.tf_f_customer c,
uop_crm1.tf_f_usernp n
WHERE (a.remove_tag = ‘0’ OR a.remove_tag = ‘7’)
AND a.user_id = b.user_id(+)
AND a.partition_id = b.partition_id(+)
AND b.vip_card_end_date(+) >= trunc(SYSDATE)
AND a.cust_id = c.cust_id
AND MOD(a.cust_id, 10000) = c.partition_id
AND a.serial_number = n.serial_number(+)
AND SYSDATE BETWEEN n.start_date(+) AND n.end_date(+)
AND EXISTS (SELECT 1
FROM uop_crm1.tf_f_user_product e
WHERE e.user_id = a.user_id
AND e.partition_id = a.partition_id
AND e.brand_code = ‘VPMN’
AND e.end_date >= SYSDATE)

这个sql会执行20度分钟

看了下执行计划

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |

| 0 | SELECT STATEMENT | | 25347 | 3292K| 285K (7)| 00:57:08 | | |
| 1 | TABLE ACCESS BY INDEX ROWID | TD_B_PRODUCT | 1 | 47 | 3 (0)| 00:00:01 | | |
|* 2 | INDEX RANGE SCAN | PK_TD_B_PRODUCT | 1 | | 2 (0)| 00:00:01 | | |
| 3 | TABLE ACCESS BY INDEX ROWID | TD_M_AREA | 1 | 23 | 2 (0)| 00:00:01 | | |
|* 4 | INDEX UNIQUE SCAN | PK_TD_M_AREA | 1 | | 1 (0)| 00:00:01 | | |
|* 5 | HASH JOIN RIGHT OUTER | | 25347 | 3292K| 285K (7)| 00:57:08 | | |
|* 6 | TABLE ACCESS FULL | TF_F_CUST_VIP | 2682 | 37548 | 47339 (6)| 00:09:29 | | |
|* 7 | HASH JOIN RIGHT OUTER | | 25347 | 2945K| 238K (7)| 00:47:40 | | |
| 8 | PARTITION RANGE ALL | | 1374 | 38472 | 15 (7)| 00:00:01 | 1 | 10 |
|* 9 | TABLE ACCESS FULL | TF_F_USERNP | 1374 | 38472 | 15 (7)| 00:00:01 | 1 | 10 |
|* 10 | HASH JOIN | | 25347 | 2252K| 238K (7)| 00:47:40 | | |
| 11 | NESTED LOOPS | | 22047 | 1679K| 223K (7)| 00:44:42 | | |
| 12 | PARTITION RANGE ALL | | 53879 | 1736K| 126K (12)| 00:25:23 | 1 | 10 |
|* 13 | TABLE ACCESS FULL | TF_F_USER_PRODUCT | 53879 | 1736K| 126K (12)| 00:25:23 | 1 | 10 |
|* 14 | TABLE ACCESS BY GLOBAL INDEX ROWID| TF_F_USER | 1 | 45 | 2 (0)| 00:00:01 | ROWID | ROWID |
|* 15 | INDEX UNIQUE SCAN | PK_TF_F_USER | 1 | | 1 (0)| 00:00:01 | | |
| 16 | PARTITION RANGE ALL | | 16M| 209M| 14056 (7)| 00:02:49 | 1 | 10 |

| 17 | INDEX FAST FULL SCAN | PK_TF_F_CUSTOMER | 16M| 209M| 14056 (7)| 00:02:49 | 1 | 10 |

Predicate Information (identified by operation id):

2 - access(“T”.”PRODUCT_ID”=:B1)
4 - access(“T1”.”AREA_CODE”=:B1)
5 - access(“A”.”USER_ID”=”B”.”USER_ID”(+) AND “A”.”PARTITION_ID”=”B”.”PARTITION_ID”(+))
6 - filter(“B”.”VIP_CARD_END_DATE”(+)>=TRUNC(SYSDATE@!))
7 - access(“A”.”SERIAL_NUMBER”=”N”.”SERIAL_NUMBER”(+))
9 - filter(“N”.”END_DATE”(+)>=SYSDATE@! AND “N”.”START_DATE”(+)<=SYSDATE@!)
10 - access(“A”.”CUST_ID”=”C”.”CUST_ID” AND “C”.”PARTITION_ID”=MOD(“A”.”CUST_ID”,10000))
13 - filter(“E”.”BRAND_CODE”=’VPMN’ AND “E”.”END_DATE”>=SYSDATE@! AND “E”.”START_DATE”<=SYSDATE@!)
14 - filter(“A”.”REMOVE_TAG”=’0’ OR “A”.”REMOVE_TAG”=’7’)
15 - access(“A”.”USER_ID”=”E”.”USER_ID” AND “A”.”PARTITION_ID”=”E”.”PARTITION_ID”)

做了2处修改后,执行1s内出结果,执行计划如下:

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |

| 0 | SELECT STATEMENT | | 8 | 936 | 11635 (1)| 00:02:20 | | |
| 1 | TABLE ACCESS BY INDEX ROWID | TD_B_PRODUCT | 1 | 47 | 3 (0)| 00:00:01 | | |
|* 2 | INDEX RANGE SCAN | PK_TD_B_PRODUCT | 1 | | 2 (0)| 00:00:01 | | |
| 3 | TABLE ACCESS BY INDEX ROWID | TD_M_AREA | 1 | 23 | 2 (0)| 00:00:01 | | |
|* 4 | INDEX UNIQUE SCAN | PK_TD_M_AREA | 1 | | 1 (0)| 00:00:01 | | |
| 5 | NESTED LOOPS | | 8 | 936 | 11635 (1)| 00:02:20 | | |
| 6 | NESTED LOOPS OUTER | | 7 | 728 | 11628 (1)| 00:02:20 | | |
| 7 | NESTED LOOPS | | 7 | 630 | 11613 (1)| 00:02:20 | | |
| 8 | NESTED LOOPS | | 1547 | 98K| 6956 (1)| 00:01:24 | | |
|* 9 | INDEX FAST FULL SCAN | PK_TF_F_USERNP | 1384 | 27680 | 4 (0)| 00:00:01 | | |
| 10 | INLIST ITERATOR | | | | | | | |
| 11 | TABLE ACCESS BY GLOBAL INDEX ROWID| TF_F_USER | 1 | 45 | 5 (0)| 00:00:01 | ROWID | ROWID |
|* 12 | INDEX RANGE SCAN | IDX_TF_F_USER_SN_G | 1 | | 4 (0)| 00:00:01 | | |
| 13 | PARTITION RANGE ITERATOR | | 1 | 25 | 3 (0)| 00:00:01 | KEY | KEY |
|* 14 | TABLE ACCESS BY LOCAL INDEX ROWID | TF_F_USER_PRODUCT | 1 | 25 | 3 (0)| 00:00:01 | KEY | KEY |
|* 15 | INDEX RANGE SCAN | PK_TF_F_USER_PRODUCT | 1 | | 2 (0)| 00:00:01 | KEY | KEY |
|* 16 | TABLE ACCESS BY INDEX ROWID | TF_F_CUST_VIP | 1 | 14 | 3 (0)| 00:00:01 | | |
|* 17 | INDEX RANGE SCAN | USER_ID | 1 | | 2 (0)| 00:00:01 | | |
| 18 | PARTITION RANGE ITERATOR | | 1 | 13 | 1 (0)| 00:00:01 | KEY | KEY |

|* 19 | INDEX UNIQUE SCAN | PK_TF_F_CUSTOMER | 1 | 13 | 1 (0)| 00:00:01 | KEY | KEY |

Predicate Information (identified by operation id):

2 - access(“T”.”PRODUCT_ID”=:B1)
4 - access(“T1”.”AREA_CODE”=:B1)
9 - filter(“N”.”START_DATE”