使用UNION代替OR 提升查詢效能
阿新 • • 發佈:2018-12-23
昨天一位鐵哥們通過QQ找我幫忙,問下面這個SQL能否優化
SQL> set timing on SQL> set autotrace on SQL> select count(*) rowcount_lhy 2 from swgl_ddjbxx t 3 where t.fzgs_dm = '001085' 4 and (t.lrr_dm = 'e90e3fe4237c4af988477329c7f2059e' or exists 5 (select y.kh_id 6 from khgl_khywdlxx y 7 where y.kh_id = t.kh_id 8 and y.sskhjl_dm = 'e90e3fe4237c4af988477329c7f2059e') or 9 t.kpr_dm = 'e90e3fe4237c4af988477329c7f2059e') 10 and t.xjbz = '9999' 11 and t.FROMNBGL1 = '0'; SQL> set line 300 SQL> / ROWCOUNT_LHY ------------ 60 已用時間: 00: 00: 20.53 執行計劃 ---------------------------------------------------------- Plan hash value: 1217125969 -------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 86 | 28048 (1)| 00:05:37 | | 1 | SORT AGGREGATE | | 1 | 86 | | | |* 2 | FILTER | | | | | | |* 3 | TABLE ACCESS FULL | SWGL_DDJBXX | 5926 | 497K| 28048 (1)| 00:05:37 | |* 4 | TABLE ACCESS BY INDEX ROWID| KHGL_KHYWDLXX | 1 | 57 | 5 (0)| 00:00:01 | |* 5 | INDEX RANGE SCAN | IDX_KHGL_KHYWDLXX_KHID | 1 | | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("T"."LRR_DM"='e90e3fe4237c4af988477329c7f2059e' OR "T"."KPR_DM"='e90e3fe4237c4af988477329c7f2059e' OR EXISTS (SELECT 0 FROM "KHGL_KHYWDLXX" "Y" WHERE "Y"."KH_ID"=:B1 AND "Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e')) 3 - filter("T"."FROMNBGL1"='0' AND "T"."XJBZ"='9999' AND "T"."FZGS_DM"='001085') 4 - filter("Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e') 5 - access("Y"."KH_ID"=:B1) 統計資訊 ---------------------------------------------------------- 0 recursive calls 0 db block gets 804560 consistent gets 71127 physical reads 0 redo size 516 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
看了5秒鐘,回覆哥們說把or展開成union,但是那哥們SQL確實太菜了呵呵(別罵我哈),只好幫忙寫一個了
SQL> select count(*) 2 from (select * 3 from swgl_ddjbxx t 4 where t.lrr_dm = 'e90e3fe4237c4af988477329c7f2059e' 5 and t.fzgs_dm = '001085' 6 and t.xjbz = '9999' 7 and t.FROMNBGL1 = '0' 8 union 9 select * 10 from swgl_ddjbxx t 11 where t.kpr_dm = 'e90e3fe4237c4af988477329c7f2059e' 12 and t.fzgs_dm = '001085' 13 and t.xjbz = '9999' 14 and t.FROMNBGL1 = '0' 15 union 16 select * 17 from swgl_ddjbxx t 18 where exists 19 (select y.kh_id 20 from khgl_khywdlxx y 21 where y.kh_id = t.kh_id 22 and y.sskhjl_dm = 'e90e3fe4237c4af988477329c7f2059e') 23 and t.fzgs_dm = '001085' 24 and t.xjbz = '9999' 25 and t.FROMNBGL1 = '0'); COUNT(*) ---------- 60 已用時間: 00: 00: 06.89 執行計劃 ---------------------------------------------------------- Plan hash value: 3846872744 ----------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 52263 (1)| 00:10:28 | | 1 | SORT AGGREGATE | | 1 | | | | | | 2 | VIEW | | 5996 | | | 52263 (1)| 00:10:28 | | 3 | SORT UNIQUE | | 5996 | 2238K| 6344K| 52263 (47)| 00:10:28 | | 4 | UNION-ALL | | | | | | | |* 5 | TABLE ACCESS FULL | SWGL_DDJBXX | 59 | 19234 | | 28037 (1)| 00:05:37 | |* 6 | TABLE ACCESS BY INDEX ROWID | SWGL_DDJBXX | 10 | 3260 | | 1209 (1)| 00:00:15 | |* 7 | INDEX RANGE SCAN | IDX_SWGL_DDJBXX_KPRDM | 4748 | | | 34 (0)| 00:00:01 | |* 8 | TABLE ACCESS BY INDEX ROWID | SWGL_DDJBXX | 1 | 326 | | 5 (0)| 00:00:01 | | 9 | NESTED LOOPS | | 5927 | 2216K| | 22527 (1)| 00:04:31 | | 10 | SORT UNIQUE | | 10165 | 565K| | 1916 (1)| 00:00:23 | | 11 | TABLE ACCESS BY INDEX ROWID| KHGL_KHYWDLXX | 10165 | 565K| | 1916 (1)| 00:00:23 | |* 12 | INDEX RANGE SCAN | IDX_KHGL_KHYWDLXX_SSKHJL | 10165 | | | 111 (0)| 00:00:02 | |* 13 | INDEX RANGE SCAN | IDX_SWGL_DDJBXX_KHID | 2 | | | 2 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - filter("T"."LRR_DM"='e90e3fe4237c4af988477329c7f2059e' AND "T"."FROMNBGL1"='0' AND "T"."XJBZ"='9999' AND "T"."FZGS_DM"='001085') 6 - filter("T"."FROMNBGL1"='0' AND "T"."XJBZ"='9999' AND "T"."FZGS_DM"='001085') 7 - access("T"."KPR_DM"='e90e3fe4237c4af988477329c7f2059e') 8 - filter("T"."FROMNBGL1"='0' AND "T"."XJBZ"='9999' AND "T"."FZGS_DM"='001085') 12 - access("Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e') 13 - access("Y"."KH_ID"="T"."KH_ID") 統計資訊 ---------------------------------------------------------- 1 recursive calls 0 db block gets 128422 consistent gets 10308 physical reads 0 redo size 512 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk) 1 rows processed
SQL改寫之後,執行時間由原來的20秒下降到6秒,邏輯讀由804560降低到128422,效能還是有很大提升的,到了這裡優化還沒完,可以建立一個組合索引進一步優化
create index idx on swgl_ddjbxx(fzgs_dm,xjbz,FROMNBGL1);
建立索引之後,原始的SQL執行時間,執行計劃,統計資訊如下:
SQL> select count(*) rowcount_lhy 2 from swgl_ddjbxx t 3 where t.fzgs_dm = '001085' 4 and (t.lrr_dm = 'e90e3fe4237c4af988477329c7f2059e' or exists 5 (select y.kh_id 6 from khgl_khywdlxx y 7 where y.kh_id = t.kh_id 8 and y.sskhjl_dm = 'e90e3fe4237c4af988477329c7f2059e') or 9 t.kpr_dm = 'e90e3fe4237c4af988477329c7f2059e') 10 and t.xjbz = '9999' 11 and t.FROMNBGL1 = '0'; ROWCOUNT_LHY ------------ 60 已用時間: 00: 00: 02.96 執行計劃 ---------------------------------------------------------- Plan hash value: 3049366449 -------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 86 | 506 (0)| 00:00:07 | | 1 | SORT AGGREGATE | | 1 | 86 | | | |* 2 | FILTER | | | | | | | 3 | TABLE ACCESS BY INDEX ROWID| SWGL_DDJBXX | 5926 | 497K| 506 (0)| 00:00:07 | |* 4 | INDEX RANGE SCAN | IDX | 2370 | | 12 (0)| 00:00:01 | |* 5 | TABLE ACCESS BY INDEX ROWID| KHGL_KHYWDLXX | 1 | 57 | 5 (0)| 00:00:01 | |* 6 | INDEX RANGE SCAN | IDX_KHGL_KHYWDLXX_KHID | 1 | | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("T"."LRR_DM"='e90e3fe4237c4af988477329c7f2059e' OR "T"."KPR_DM"='e90e3fe4237c4af988477329c7f2059e' OR EXISTS (SELECT 0 FROM "KHGL_KHYWDLXX" "Y" WHERE "Y"."KH_ID"=:B1 AND "Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e')) 4 - access("T"."FZGS_DM"='001085' AND "T"."XJBZ"='9999' AND "T"."FROMNBGL1"='0') 5 - filter("Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e') 6 - access("Y"."KH_ID"=:B1) 統計資訊 ---------------------------------------------------------- 1 recursive calls 0 db block gets 702767 consistent gets 0 physical reads 0 redo size 516 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
改寫的SQL:
SQL> select count(*)
2 from (select *
3 from swgl_ddjbxx t
4 where t.lrr_dm = 'e90e3fe4237c4af988477329c7f2059e'
5 and t.fzgs_dm = '001085'
6 and t.xjbz = '9999'
7 and t.FROMNBGL1 = '0'
8 union
9 select *
10 from swgl_ddjbxx t
11 where t.kpr_dm = 'e90e3fe4237c4af988477329c7f2059e'
12 and t.fzgs_dm = '001085'
13 and t.xjbz = '9999'
14 and t.FROMNBGL1 = '0'
15 union
16 select *
17 from swgl_ddjbxx t
18 where exists
19 (select y.kh_id
20 from khgl_khywdlxx y
21 where y.kh_id = t.kh_id
22 and y.sskhjl_dm = 'e90e3fe4237c4af988477329c7f2059e')
23 and t.fzgs_dm = '001085'
24 and t.xjbz = '9999'
25 and t.FROMNBGL1 = '0');
COUNT(*)
----------
60
已用時間: 00: 00: 00.53
執行計劃
----------------------------------------------------------
Plan hash value: 2947849958
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 3469 (1)| 00:00:42 |
| 1 | SORT AGGREGATE | | 1 | | | | |
| 2 | VIEW | | 5995 | | | 3469 (1)| 00:00:42 |
| 3 | SORT UNIQUE | | 5995 | 2238K| 4760K| 3469 (86)| 00:00:42 |
| 4 | UNION-ALL | | | | | | |
|* 5 | TABLE ACCESS BY INDEX ROWID | SWGL_DDJBXX | 59 | 19234 | | 506 (0)| 00:00:07 |
|* 6 | INDEX RANGE SCAN | IDX | 2370 | | | 12 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | SWGL_DDJBXX | 10 | 3260 | | 50 (0)| 00:00:01 |
| 8 | BITMAP CONVERSION TO ROWIDS | | | | | | |
| 9 | BITMAP AND | | | | | | |
| 10 | BITMAP CONVERSION FROM ROWIDS| | | | | | |
|* 11 | INDEX RANGE SCAN | IDX | 2370 | | | 12 (0)| 00:00:01 |
| 12 | BITMAP CONVERSION FROM ROWIDS| | | | | | |
|* 13 | INDEX RANGE SCAN | IDX_SWGL_DDJBXX_KPRDM | 2370 | | | 34 (0)| 00:00:01 |
|* 14 | HASH JOIN RIGHT SEMI | | 5926 | 2216K| | 2423 (1)| 00:00:30 |
| 15 | TABLE ACCESS BY INDEX ROWID | KHGL_KHYWDLXX | 10165 | 565K| | 1916 (1)| 00:00:23 |
|* 16 | INDEX RANGE SCAN | IDX_KHGL_KHYWDLXX_SSKHJL | 10165 | | | 111 (0)| 00:00:02 |
| 17 | TABLE ACCESS BY INDEX ROWID | SWGL_DDJBXX | 5926 | 1886K| | 506 (0)| 00:00:07 |
|* 18 | INDEX RANGE SCAN | IDX | 2370 | | | 12 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter("T"."LRR_DM"='e90e3fe4237c4af988477329c7f2059e')
6 - access("T"."FZGS_DM"='001085' AND "T"."XJBZ"='9999' AND "T"."FROMNBGL1"='0')
11 - access("T"."FZGS_DM"='001085' AND "T"."XJBZ"='9999' AND "T"."FROMNBGL1"='0')
filter("T"."FROMNBGL1"='0' AND "T"."XJBZ"='9999' AND "T"."FZGS_DM"='001085')
13 - access("T"."KPR_DM"='e90e3fe4237c4af988477329c7f2059e')
14 - access("Y"."KH_ID"="T"."KH_ID")
16 - access("Y"."SSKHJL_DM"='e90e3fe4237c4af988477329c7f2059e')
18 - access("T"."FZGS_DM"='001085' AND "T"."XJBZ"='9999' AND "T"."FROMNBGL1"='0')
統計資訊
----------------------------------------------------------
1 recursive calls
0 db block gets
25628 consistent gets
0 physical reads
0 redo size
512 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1 rows processed
由於我不能直接連線到DB,這個SQL的優化就到此為止。