使用UNION代替OR 提升查询性能
Posted robinson1988
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用UNION代替OR 提升查询性能相关的知识,希望对你有一定的参考价值。
昨天一位铁哥们通过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的优化就到此为止。
以上是关于使用UNION代替OR 提升查询性能的主要内容,如果未能解决你的问题,请参考以下文章