您的位置:首页 > 数据库

SQL优化一例:注意视图对性能的影响

2011-05-26 15:30 453 查看
近日在生产库ADDM中捕捉到了一些列SQL语句,绝大部分通过索引优化都能够搞定,但是如下一句SQL语句却非常难缠。通过索引优化效果一直不理想,最后进一步分析得出该语句上层视图用了×查询出了ACH大数据表的所有字段(数百万记录,50个字段的表),而我们在SQL中只用到了区区几个字段,于是决定抛弃该视图,把视图中相关逻辑直接在上层SQL中展现。通过该动作,大大降低了对关键表的查询开销,得以高效优化。

问题SQL语句:
Select Count(Distinct e.Entry_Id)
From v_ACE e
Where e.Agent_Code = :B8 And Not Exists
(Select Ed.Entry_Id From AED Ed Where e.Entry_Id = Ed.Entry_Id And Ed.Deleted_Flag = '0') And
(:B7 Is Null Or e.Entry_Id = :B7) And (:B6 Is Null Or e.Container_Num = :B6) And (:B5 = '0' Or e.Decl_Port = :B5) And
(:B4 Is Null Or Trunc(e.d_Date) >= :B3) And (:B2 Is Null Or Trunc(e.d_Date) <= :B1)

我们看看视图:v_ACE
create or replace view v_ACE as
select tmp.*,
status.cus_operation_status,
status.control_type,
status.data_source,
status.customs_mode,
status.predigest_mode,
status.goods_type,
status.risk_type,
status.control_date,
status.e_supervision_type
from
(select rownum as id,head.*,con.container_num
from AEC t
inner join AEH head on t.entry_id = head.entry_id
inner join AC con on t.container_id = con.id and head.deleted_flag='0' and con.deleted_flag='0')tmp
left join AESN status on tmp.entry_id=status.entry_id order by tmp.id asc

--------------------------------------------------------------------------------
执行计划
--------------------------------------------------------------------------------
[Execution Plan Information]

------------------------------------------------------------------------------------------------------------------------
| Operation                                                    | PHV/Object Name               |  Rows | Bytes| Cost   |
------------------------------------------------------------------------------------------------------------------------
|000[000]SELECT STATEMENT                                       |---- 2192985071.0 ----         |       |      |  10761 |
|001[001]SORT GROUP BY                                          |                               |     1 |   89 |        |
|002[002] NESTED LOOPS OUTER                                    |                               |     1 |   89 |  10761 |
|003[003]  HASH JOIN RIGHT ANTI                                 |                               |     1 |   70 |  10760 |
|004[004]   INDEX FAST FULL SCAN                                |IDX_A_E_C                      |   685K|   13M|    841 |
|005[004]   VIEW                                                |                               |   386K|   18M|   7675 |
|006[005]    COUNT                                              |                               |       |      |        |
|007[006]     HASH JOIN                                         |                               |   386K|   29M|   7675 |
|008[007]      INDEX FAST FULL SCAN                             |IDX_TEST3                      |   780K|   14M|    830 |
|009[007]      HASH JOIN                                        |                               |   385K|   22M|   4289 |
|010[008]       INDEX FAST FULL SCAN                            |IDX_A_E_H                      |   362K|   13M|   1346 |
|011[008]       TABLE ACCESS FULL                               |AEC                            |   757K|   15M|    766 |
|012[003]  INDEX UNIQUE SCAN                                    |PK_A_E_S_N                     |     1 |   19 |      1 |
------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
优化方法
--------------------------------------------------------------------------------
1、新建索引
create index IDX_ADCPHC_CONTAINER_3 on ADCPHC_CONTAINER (DELETED_FLAG, ID, CONTAINER_NUM)
tablespace TBL_INDEX
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
minextents 1
maxextents unlimited
);

2、重写SQL语句
Select Count(Distinct head.entry_id)
from AEC t
inner join A_E_H head on t.entry_id = head.entry_id and head.deleted_flag='0'
And head.Agent_Code = :B8
And (:B7 Is Null Or head.Entry_Id = :B7)
And (:B5 = '0' Or head.Decl_Port = :B5)
And (:B4 Is Null Or Trunc(head.d_Date) >= :B3)
And (:B2 Is Null Or Trunc(head.d_Date) <= :B1)
inner join AC con on t.container_id = con.id  and con.deleted_flag='0'
And (:B6 Is Null Or con.Container_Num = :B6)
left join AESN status on head.entry_id=status.entry_id
And Not Exists
(Select Ed.Entry_Id From AED Ed Where head.Entry_Id = Ed.Entry_Id And Ed.Deleted_Flag = '0'     )

--------------------------------------------------------------------------------
预计优化后执行计划--COST由10761提升到1462,在索引优化的基础上效率提升7倍
--------------------------------------------------------------------------------
SELECT STATEMENT, GOAL = ALL_ROWS                               Cost=1462   Cardinality=1   Bytes=81
SORT GROUP BY              Cardinality=1   Bytes=81
NESTED LOOPS OUTER                                        Cost=1462   Cardinality=1   Bytes=81
NESTED LOOPS                                         Cost=1460   Cardinality=1   Bytes=81
NESTED LOOPS                                        Cost=1458   Cardinality=1   Bytes=62
INDEX FAST FULL SCAN   Object owner=OPERATION  Object name=IDX_A_E_H_M         Cost=1456   Cardinality=1   Bytes=40
INDEX RANGE SCAN       Object owner=OPERATION  Object name=IDX_A_E_C           Cost=2      Cardinality=1   Bytes=22
INDEX RANGE SCAN        Object owner=OPERATION  Object name=IDX_TEST3           Cost=2      Cardinality=1   Bytes=19
VIEW Object owner=SYS                                    Cost=2      Cardinality=1
FILTER
INDEX UNIQUE SCAN      Object owner=OPERATION  Object name=PK_A_E_S_N          Cost=2      Cardinality=1   Bytes=19
INDEX RANGE SCAN       Object owner=OPERATION  Object name=IDX_ADCPHC_ENTRY_DECLARE    Cost=3      Cardinality=1   Bytes=21
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息