您的位置:首页 > 其它

union union all group by 优化一例

2016-11-14 15:26 274 查看

一. 原执行计划

     本SQL是公司显示屏报表SQL,每2min更新一次

SQL> explain plan for select distinct id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000 and t.pay_date <= '2016-11-14'
union
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 and t.pay_date <= '2016-11-14');

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 398117206

--------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                         |   168K|  2800K|       |  4009   (2)| 00:00:49 |
|   1 |  VIEW                |                         |   168K|  2800K|       |  4009   (2)| 00:00:49 |
|   2 |   SORT UNIQUE        |                         |   168K|  6093K|    15M|  4009   (2)| 00:00:49 |
|   3 |    UNION-ALL         |                         |       |       |       |            |          |
|*  4 |     TABLE ACCESS FULL| CRF_P2P_ACCOUNT_INFO    |   167K|  6067K|       |  2357   (2)| 00:00:29 |
|*  5 |     TABLE ACCESS FULL| ZH_CRF_P2P_ACCOUNT_INFO |   759 | 27324 |       |    12   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000 AND "T"."PAY_DATE"<='2016-11-14')
5 - filter("T"."LOAN_AMOUNT"<=200000 AND "T"."PAY_DATE"<='2016-11-14')

18 rows selected.

SQL>


二.去日期:

日期每次都是取当前日期,不起任何作用,完全可以去掉

SQL> select distinct id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 );

159471 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 398117206

--------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                         |   168K|  2800K|       |  3608   (1)| 00:00:44 |
|   1 |  VIEW                |                         |   168K|  2800K|       |  3608   (1)| 00:00:44 |
|   2 |   SORT UNIQUE        |                         |   168K|  4281K|    11M|  3608   (2)| 00:00:44 |
|   3 |    UNION-ALL         |                         |       |       |       |            |          |
|*  4 |     TABLE ACCESS FULL| CRF_P2P_ACCOUNT_INFO    |   167K|  4263K|       |  2339   (1)| 00:00:29 |
|*  5 |     TABLE ACCESS FULL| ZH_CRF_P2P_ACCOUNT_INFO |   759 | 18975 |       |    12   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000)
5 - filter("T"."LOAN_AMOUNT"<=200000)

Statistics
----------------------------------------------------------
1  recursive calls
0  db block gets
10591  consistent gets
0  physical reads
0  redo size
5167400  bytes sent via SQL*Net to client
117410  bytes received via SQL*Net from client
10633  SQL*Net roundtrips to/from client
1  sorts (memory)
0  sorts (disk)
159471  rows processed

SQL>


三.加索引:

看到执行计划全表扫描,常规想法加索引,但此处特殊在索引的选择性还是可以的,但因为数据原因大部分都是符合要求的,17w的数据有15w多都要读

所以索引不走,Oracle如果按反常思维,比如说先找出不符合条件的排除再全读可能索引会快,本还想按此思维改写。

SQL> create index clspuser.crf_p2p_loan_amount_idx on crf_p2p_account_info(loan_amount);

Index created.

SQL>
索引没用,删了
SQL> drop index  crf_p2p_loan_amount_idx ;

Index dropped.

SQL>


四. 组合索引

这里添加联合索引,可见IFFS要比TAF快多了

create index  clspuser.crf_p2p_loan_amount_uidx on clspuser.crf_p2p_account_info (loan_amount, id_card) online;

SQL> explain plan for  select distinct id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 );

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1932924644

------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                          |   168K|  2800K|       |  1459   (2)| 00:00:18 |
|   1 |  VIEW                   |                          |   168K|  2800K|       |  1459   (2)| 00:00:18 |
|   2 |   SORT UNIQUE           |                          |   168K|  4281K|    11M|  1459   (3)| 00:00:18 |
|   3 |    UNION-ALL            |                          |       |       |       |            |          |
|*  4 |     INDEX FAST FULL SCAN| CRF_P2P_LOAN_AMOUNT_UIDX |   167K|  4263K|       |   189   (3)| 00:00:03 |
|*  5 |     TABLE ACCESS FULL   | ZH_CRF_P2P_ACCOUNT_INFO  |   759 | 18975 |       |    12   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000)
5 - filter("T"."LOAN_AMOUNT"<=200000)

18 rows selected.

SQL>


五. 去掉distinct

SQL> explain plan for select  id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 );

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1932924644

------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                          |   168K|  2800K|       |  1459   (2)| 00:00:18 |
|   1 |  VIEW                   |                          |   168K|  2800K|       |  1459   (2)| 00:00:18 |
|   2 |   SORT UNIQUE           |                          |   168K|  4281K|    11M|  1459   (3)| 00:00:18 |
|   3 |    UNION-ALL            |                          |       |       |       |            |          |
|*  4 |     INDEX FAST FULL SCAN| CRF_P2P_LOAN_AMOUNT_UIDX |   167K|  4263K|       |   189   (3)| 00:00:03 |
|*  5 |     TABLE ACCESS FULL   | ZH_CRF_P2P_ACCOUNT_INFO  |   759 | 18975 |       |    12   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000)
5 - filter("T"."LOAN_AMOUNT"<=200000)

18 rows selected.

SQL>


六. 去掉select外围

这里就是刚才提到的多此一举了

SQL> explain plan for select distinct t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000;

Explained.

SQL>
SQL>  select * from  table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2415738997

-----------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                          |   159K|  4041K|       |  1414   (3)| 00:00:17 |
|   1 |  SORT UNIQUE           |                          |   159K|  4041K|    11M|  1414   (3)| 00:00:17 |
|   2 |   UNION-ALL            |                          |       |       |       |            |          |
|*  3 |    INDEX FAST FULL SCAN| CRF_P2P_LOAN_AMOUNT_UIDX |   167K|  4263K|       |   189   (3)| 00:00:03 |
|*  4 |    TABLE ACCESS FULL   | ZH_CRF_P2P_ACCOUNT_INFO  |   759 | 18975 |       |    12   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------

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

3 - filter("T"."LOAN_AMOUNT"<=200000)
4 - filter("T"."LOAN_AMOUNT"<=200000)

17 rows selected.

SQL>


七. 用union all

union all只是把2个结果拼接在一起,不会排序去重,这对于不用排序去重的性能提高尤为明显,但本SQL还是要去重操作的,

这里把去重放到外面了效果比较明显了已经,因为这里省去了SORT但是distinct效果还是不尽如人意

SQL> explain plan for select distinct id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union all
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 );

Explained.

SQL> select * from  table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1571881081

------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                          |   168K|  2800K|       |  1144   (2)| 00:00:14 |
|   1 |  HASH UNIQUE            |                          |   168K|  2800K|  7960K|  1144   (2)| 00:00:14 |
|   2 |   VIEW                  |                          |   168K|  2800K|       |   201   (2)| 00:00:03 |
|   3 |    UNION-ALL            |                          |       |       |       |            |          |
|*  4 |     INDEX FAST FULL SCAN| CRF_P2P_LOAN_AMOUNT_UIDX |   167K|  4263K|       |   189   (3)| 00:00:03 |
|*  5 |     TABLE ACCESS FULL   | ZH_CRF_P2P_ACCOUNT_INFO  |   759 | 18975 |       |    12   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000)
5 - filter("T"."LOAN_AMOUNT"<=200000)

18 rows selected.

SQL>


八. 用group by

这里用分组操作代替排序去重 ,效果已经很明显了,至此原本49S的SQL也已优化到3S

SQL> explain plan for select  id_card
from (select t.id_card
from clspuser.crf_p2p_account_info t
where t.loan_amount <= 200000
union all
select t.id_card
from clspuser.zh_crf_p2p_account_info t
where t.loan_amount <= 200000 ) a group by a.id_card;

Explained.

SQL> select * from  table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1930908435

----------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                          |   168K|  2800K|   218  (10)| 00:00:03 |
|   1 |  HASH GROUP BY          |                          |   168K|  2800K|   218  (10)| 00:00:03 |
|   2 |   VIEW                  |                          |   168K|  2800K|   201   (2)| 00:00:03 |
|   3 |    UNION-ALL            |                          |       |       |            |          |
|*  4 |     INDEX FAST FULL SCAN| CRF_P2P_LOAN_AMOUNT_UIDX |   167K|  4263K|   189   (3)| 00:00:03 |
|*  5 |     TABLE ACCESS FULL   | ZH_CRF_P2P_ACCOUNT_INFO  |   759 | 18975 |    12   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

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

4 - filter("T"."LOAN_AMOUNT"<=200000)
5 - filter("T"."LOAN_AMOUNT"<=200000)

18 rows selected.

SQL>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: