SELECT
a.id AS order_id ,b.s_id AS bill_id,
d.id AS sub_order_id,
d.deal_oper_id
FROM EM_ORDER PARTITION(EM_ORDER_201611) A,
M_101_ID_2_GID B,
ER_ORDER_ORDER C,
EM_ORDER D,
EE_ORDER_PF_WORK E
WHERE A.SPEC_ID = 3010200004
AND A.ID = B.T_ID
AND A.STATUS_ID = 1000007
AND A.COMPLETE_TIME >= TO_DATE('2016-11-14 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
and A.COMPLETE_TIME <= TO_DATE('2016-11-14 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
AND A.ID = C.A_ORDER_ID
AND C.B_ORDER_ID = D.ID
AND D.ID = E.ORDER_ID
AND e.work_type_id = 1001411
AND ( d.deal_oper_id IS NULL --无处理人
OR (SELECT f_chk_idcard(x.identity_number)
FROM dm_staff x
WHERE x.id = d.deal_oper_id) = 0 --处理人身份证不合法
);
表大小:
size_mb segement_name
1 4595.0625 EE_ORDER_PF_WORK
2 40159.0625 EM_ORDER
3 20059.0625 ER_ORDER_ORDER
4 20770.0625 M_101_ID_2_GID
dm_staff 不值一提, 20万条数据。
1 Plan hash value: 309883988
2
3 --------------------------------------------------------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
5 --------------------------------------------------------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 1 | 130 | | 1218K (1)| 04:03:44 | | |
7 |* 1 | FILTER | | | | | | | | |
8 | 2 | NESTED LOOPS | | 21005 | 2666K| | 1166K (1)| 03:53:19 | | |
9 | 3 | NESTED LOOPS | | 21791 | 2666K| | 1166K (1)| 03:53:19 | | |
10 |* 4 | HASH JOIN | | 21791 | 2234K| 17M| 1079K (1)| 03:35:53 | | |
11 | 5 | NESTED LOOPS | | 183K| 15M| | 907K (1)| 03:01:32 | | |
12 | 6 | NESTED LOOPS | | 183K| 15M| | 907K (1)| 03:01:32 | | |
13 | 7 | NESTED LOOPS | | 183K| 11M| | 358K (1)| 01:11:37 | | |
14 |* 8 | TABLE ACCESS BY GLOBAL INDEX ROWID| EM_ORDER | 106K| 3631K| | 39284 (1)| 00:07:52 | 8 | 8 |
15 |* 9 | INDEX RANGE SCAN | IDX_EM_ORDER_COMP_TIME | 44669 | | | 330 (0)| 00:00:04 | | |
16 |* 10 | INDEX RANGE SCAN | IDX_ER_ORDER_ORDER_OO | 2 | 56 | | 3 (0)| 00:00:01 | | |
17 |* 11 | INDEX UNIQUE SCAN | PK_EM_ORDER | 1 | | | 2 (0)| 00:00:01 | | |
18 | 12 | TABLE ACCESS BY GLOBAL INDEX ROWID | EM_ORDER | 1 | 26 | | 3 (0)| 00:00:01 | ROWID | ROWID |
19 | 13 | PARTITION RANGE ALL | | 10M| 161M| | 156K (1)| 00:31:22 | 1 | 10 |
20 |* 14 | TABLE ACCESS FULL | EE_ORDER_PF_WORK | 10M| 161M| | 156K (1)| 00:31:22 | 1 | 10 |
21 |* 15 | INDEX RANGE SCAN | IDX_101_T_ID | 1 | | | 3 (0)| 00:00:01 | | |
22 | 16 | TABLE ACCESS BY GLOBAL INDEX ROWID | M_101_ID_2_GID | 1 | 25 | | 4 (0)| 00:00:01 | ROWID | ROWID |
23 | 17 | TABLE ACCESS BY INDEX ROWID | DM_STAFF | 1 | 20 | | 3 (0)| 00:00:01 | | |
24 |* 18 | INDEX UNIQUE SCAN | PK_DM_STAFF | 1 | | | 2 (0)| 00:00:01 | | |
25 --------------------------------------------------------------------------------------------------------------------------------------------
26
27 Predicate Information (identified by operation id):
28 ---------------------------------------------------
29
30 1 - filter( (SELECT "F_CHK_IDCARD"("X"."IDENTITY_NUMBER") FROM "QWZW_ER"."DM_STAFF" "X" WHERE "X"."ID"=:B1)=0)
31 4 - access("D"."ID"="E"."ORDER_ID")
32 8 - filter("A"."SPEC_ID"=3010200004 AND "A"."STATUS_ID"=1000007)
33 9 - access("A"."COMPLETE_TIME">=TO_DATE(' 2016-11-16 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "A"."COMPLETE_TIME"<=TO_DATE('
34 2016-11-16 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
35 filter(TBL$OR$IDX$PART$NUM("QWZW_ER"."EM_ORDER",0,1,0,ROWID)=8)
36 10 - access("A"."ID"="C"."A_ORDER_ID")
37 11 - access("C"."B_ORDER_ID"="D"."ID")
38 14 - filter("E"."WORK_TYPE_ID"=1001411)
39 15 - access("A"."ID"="B"."T_ID")
40 filter("B"."T_ID" IS NOT NULL)
41 18 - access("X"."ID"=:B1)
---- 这个估计 7 8 小时都跑不完。 反正我执行过1个多小时, 受不了杀了。 如果你不能一眼看出 这个的问题的话, 证明 你还需要修炼。 信不信 有你
性能问题在 4 , 14。
改SQL:为
SELECT
'开通单' AS spec_name,
a.id AS order_id ,b.s_id AS bill_id,
d.id AS sub_order_id,
---x.s_id task_id,
d.deal_oper_id
FROM EM_ORDER PARTITION(EM_ORDER_201611) A,
M_101_ID_2_GID B,
ER_ORDER_ORDER C,
EM_ORDER D
WHERE A.SPEC_ID = 3010200004
AND A.ID = B.T_ID
AND A.STATUS_ID = 1000007
AND A.COMPLETE_TIME >= TO_DATE('2016-11-18 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
and A.COMPLETE_TIME <= TO_DATE('2016-11-18 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
AND A.ID = C.A_ORDER_ID
AND C.B_ORDER_ID = D.ID
AND exists( select 1 from EE_ORDER_PF_WORK E where D.ID = E.ORDER_ID AND e.work_type_id = 1001411 )
AND ( d.deal_oper_id IS NULL --无处理人
OR (SELECT f_chk_idcard(x.identity_number)
FROM dm_staff x
WHERE x.id = d.deal_oper_id) = 0 --处理人身份证不合法
) ;
添加hints
/*+ use_nl(a,b) use_nl(a,c) use_nl(c,d) use_nl(a,dx) leading(a) */ /*+ nl_sj */
1 Plan hash value: 1576200999
2
3 -----------------------------------------------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
5 -----------------------------------------------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 3537 | 449K| 1372K (1)| 04:34:26 | | |
7 |* 1 | FILTER | | | | | | | |
8 | 2 | NESTED LOOPS | | 19483 | 2473K| 1372K (1)| 04:34:26 | | |
9 | 3 | NESTED LOOPS | | 20212 | 2473K| 1372K (1)| 04:34:26 | | |
10 | 4 | NESTED LOOPS SEMI | | 20212 | 2072K| 1291K (1)| 04:18:16 | | |
11 | 5 | NESTED LOOPS | | 169K| 14M| 844K (1)| 02:48:57 | | |
12 | 6 | NESTED LOOPS | | 169K| 10M| 334K (1)| 01:07:00 | | |
13 |* 7 | TABLE ACCESS BY GLOBAL INDEX ROWID| EM_ORDER | 98540 | 3368K| 39284 (1)| 00:07:52 | 8 | 8 |
14 |* 8 | INDEX RANGE SCAN | IDX_EM_ORDER_COMP_TIME | 44669 | | 330 (0)| 00:00:04 | | |
15 |* 9 | INDEX RANGE SCAN | IDX_ER_ORDER_ORDER_OO | 2 | 56 | 3 (0)| 00:00:01 | | |
16 | 10 | TABLE ACCESS BY GLOBAL INDEX ROWID | EM_ORDER | 1 | 26 | 3 (0)| 00:00:01 | ROWID | ROWID |
17 |* 11 | INDEX UNIQUE SCAN | PK_EM_ORDER | 1 | | 2 (0)| 00:00:01 | | |
18 |* 12 | TABLE ACCESS BY GLOBAL INDEX ROWID | EE_ORDER_PF_WORK | 1257K| 19M| 3 (0)| 00:00:01 | ROWID | ROWID |
19 |* 13 | INDEX UNIQUE SCAN | PK_EE_ORDER_PF_WORK | 1 | | 2 (0)| 00:00:01 | | |
20 |* 14 | INDEX RANGE SCAN | IDX_101_T_ID | 1 | | 3 (0)| 00:00:01 | | |
21 | 15 | TABLE ACCESS BY GLOBAL INDEX ROWID | M_101_ID_2_GID | 1 | 25 | 4 (0)| 00:00:01 | ROWID | ROWID |
22 | 16 | TABLE ACCESS BY INDEX ROWID | DM_STAFF | 1 | 20 | 3 (0)| 00:00:01 | | |
23 |* 17 | INDEX UNIQUE SCAN | PK_DM_STAFF | 1 | | 2 (0)| 00:00:01 | | |
24 -----------------------------------------------------------------------------------------------------------------------------------
25
26 Predicate Information (identified by operation id):
27 ---------------------------------------------------
28
29 1 - filter("D"."DEAL_OPER_ID" IS NULL OR (SELECT "F_CHK_IDCARD"("X"."IDENTITY_NUMBER") FROM "QWZW_ER"."DM_STAFF" "X"
30 WHERE "X"."ID"=:B1)=0)
31 7 - filter("A"."SPEC_ID"=3010200004 AND "A"."STATUS_ID"=1000007)
32 8 - access("A"."COMPLETE_TIME">=TO_DATE(' 2016-11-18 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
33 "A"."COMPLETE_TIME"<=TO_DATE(' 2016-11-18 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
34 filter(TBL$OR$IDX$PART$NUM("QWZW_ER"."EM_ORDER",0,1,0,ROWID)=8)
35 9 - access("A"."ID"="C"."A_ORDER_ID")
36 11 - access("C"."B_ORDER_ID"="D"."ID")
37 12 - filter("E"."WORK_TYPE_ID"=1001411)
38 13 - access("D"."ID"="E"."ORDER_ID")
39 14 - access("A"."ID"="B"."T_ID")
40 filter("B"."T_ID" IS NOT NULL)
41 17 - access("X"."ID"=:B1)
---- 首次执行 大概在 4分钟吧, 再次执行 只需要 47S 左右。 结果大概 3千条数据。
此致 优化结束。
另外说一句 PK_EE_ORDER_PF_WORK 索引我也压缩了一把, 因为 表4.5G, 索引3.5G, 这就是扯淡!!! 压缩后大概1G 左右。 这个其实侧面说明了数据堆积。
规避 我想到了想到了物化视图。 1 增量情况下 我也想到了物化视图。 下面详细说明。
后记, 这种大表, 其实我的想法是 做成 物化视图, 物化视图 ora_hash(连接字段,8) 分区 , EM_ORDER 做成range + ora_hash(连接字段,8) 分区 的物化视图。
这几个表的 日增量 最大不过100M, 但是需要保存一年的数据, commit, 提交时候 刷新物化视图,保证 无索引情况下 结果秒出.