连续两个公司都作为外派人员到客户方工作,缺少归属感的同时,对数据库技术的热爱是我唯一的安慰,毕竟这是自己喜欢的事情,还可以做下去。
因为客户项目的需要,我又开始接触Oracle,大部分工作在工作流的优化和业务数据的排查上。为了更好的做这份工作,我有参考过oracle达人,Oracle.10g性能分析与优化思路,基于海量数据的数据库设计与优化等书籍,以及案例学习SQL优化的视频等。基本上我工作中接触的主要是Oracle SQl的优化,基于长时间做SQL优化工作,现在对Oracle的SQL优化做一下自己的总结。
已知,Oracle10G以后执行计划使用基于CBO: Cost-Based Optimization 基于代价的优化器。当然在oracle 10G运行的SQL执行计划肯定是系统以为的最优了,很多时候没有办法看出优化点,不管怎么改都不比原来的性能好。怎么办呢?我每次还是傻傻的看着执行计划研究半天,很多时候这是不需要的,或者是有更快的方法发现问题所在。
当然,每个人习惯和优化思路都会有不同,优化问题的处理也会不同。基于最近我优化一个程序的四个修改点,程序有原来的7个小时左右缩短为1小时左右执行。总结下我的步骤和优化思路。
1、直接观察表的数据量和表结构属性,不拘泥考虑执行计划的最优 (大数据表利用全表 Hash关联)
简写原SQL:
SELECT count(1)
FROM Z_MID_R3_BOM_ORG1 A
WHERE trunc(a.DATUV)<=trunc(sysdate) and trunc(a.DATUB) >=trunc(sysdate)
and exists (select 1 from rpt_fp_shortage_order c
where instr(a.name,c.mtm)>0
and a.werks= c.siteid)
and exists (select 1 from mst_bomcomponentsalt b
where INSTR(b.bomid,a.name)>0
and a.idnrk=b.ALTERNATEITEM
and a.werks=b.siteid);
实际这条SQL的结果集大概在20多万条记录,结果集插入另外一张表。Z_MID_R3_BOM_ORG1表和MST_BOMCOMPONENTSALT 表的数据量在一百多万条记录,RPT_FP_SHORTAGE_ORDER 表的数据量在7000条左右。
执行计划:
SELECT STATEMENT ALL_ROWSCost: 2,595 Bytes: 64 Cardinality: 1
5 FILTER
1 TABLE ACCESS FULL TABLE PRDABPPCDB.Z_MID_R3_BOM_ORG1 Cost: 1,198 Bytes: 55,616 Cardinality: 869
2 TABLE ACCESS FULL TABLE PRDABPPCDB.RPT_FP_SHORTAGE_ORDER Cost: 3 Bytes: 17 Cardinality: 1
4 TABLE ACCESS BY INDEX ROWID TABLE PRDABPPCDB.MST_BOMCOMPONENTSALT Cost: 91 Bytes: 48 Cardinality: 1
3 INDEX FAST FULL SCAN INDEX PRDABPPCDB.S9525213703_2688 Cost: 3 Cardinality: 195
由执行计划可知,PRDABPPCDB.MST_BOMCOMPONENTSALT 表使用快速索引扫描,看似已经是最优。能利用的表属性索引已经使用了。但是近20万条记录,观察日志发现这一步骤插入的时间用了快2个小时。利用全表 Hash关联,修改后插入表的时间约为3分钟内执行完。
修改后的SQL:
SELECT count(1)
FROM Z_MID_R3_BOM_ORG1 A
WHERE trunc(a.DATUV)<=trunc(sysdate) and trunc(a.DATUB) >=trunc(sysdate)
and exists (select 1 from rpt_fp_shortage_order c
where instr(a.name,c.mtm)>0
and a.werks= c.siteid)
and exists (select /*+FULL(B)*/ 1 from mst_bomcomponentsalt b
where INSTR(b.bomid,a.name)>0
and a.idnrk=b.ALTERNATEITEM
and a.werks=b.siteid);
修改后的执行计划:
Plan
SELECT STATEMENT ALL_ROWSCost: 8,748 Bytes: 111 Cardinality: 1
6 SORT AGGREGATE Bytes: 111 Cardinality: 1
5 FILTER
3 HASH JOIN SEMI Cost: 8,676 Bytes: 111 Cardinality: 1
1 TABLE ACCESS FULL TABLE PRDABPPCDB.Z_MID_R3_BOM_ORG1 Cost: 2,493 Bytes: 107,280 Cardinality: 1,788
2 TABLE ACCESS FULL TABLE PRDABPPCDB.MST_BOMCOMPONENTSALT Cost: 6,172 Bytes: 52,636,539 Cardinality: 1,032,089
4 TABLE ACCESS FULL TABLE PRDABPPCDB.RPT_FP_SHORTAGE_ORDER Cost: 72 Bytes: 4,389 Cardinality: 133
2、拆分SQL,分段执行观察整个SQL语句的block,有针对性优化
此处的优化是在表z_dim_product (数据量20万左右)上建立函数索引,lpad(product,18,‘0‘)
简写SQL:
SELECT MAX (hier11_code)
FROM z_dim_product
WHERE substr(product,length(product)-9,10) = b.ITEM (b 表是另一个关联表)
修改后的SQL:
SELECT MAX (hier11_code)
FROM z_dim_product
WHERE lpad(product,18,‘0‘) = lpad(b.ITEM,18,‘0‘)
3、大表优化充分利用分区和分区的索引
4、从业务角度调整逻辑,改写SQL,这种方法往往是所有优化里效果最明显的。
..........
后面3\4 的方法没有再上传SQL,有时间会继续记录个人的优化总结